C# insert string and images into word via openxml

Install-Package DocumentFormat.OpenXml;
Install-Package System.Drawing.Common;

 

 

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System.Diagnostics;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;

namespace ConsoleApp29
{
    internal class Program
    {
        static Random rnd;
        private const UInt32 WordMaxPage = 31680;

        // Clamp A0 dimensions to Word's maximum supported
        private const UInt32 A0Width = WordMaxPage;
        private const UInt32 A0Height = WordMaxPage;

        // Margins in twips (1 inch = 1440 twips)
        private const int Margin = 1440;

        // EMU conversion (1 inch = 914400 EMU)
        private const long EmusPerInch = 914400;

        static void Main(string[] args)
        {
            string wordFile = $"DOC_{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.docx";
            InsertStringToWordFile(wordFile);

            InsertImagesToWordFile(wordFile);

            var proc = new Process()
            {
                StartInfo=new ProcessStartInfo()
                {
                    FileName = wordFile,
                    UseShellExecute = true
                }
            };
            proc.Start();
        }

        private static void InsertImagesToWordFile(string wordFile)
        {
            var imgDir = @"../../../Images";
            if (Directory.Exists(imgDir))
            {
                var imgsList = Directory.GetFiles(imgDir).ToList();
                InsertImagesListIntoWord(wordFile, imgsList);
            }
        }

        private static void InsertStringToWordFile(string wordFile)
        {
            rnd=new Random();
            CreateOrOrOpenWordFileInsertString(wordFile, "SMOOTHTECH", 50, "center", true);
            CreateOrOrOpenWordFileInsertString(wordFile, "Focus", 50, "left", true);
            CreateOrOrOpenWordFileInsertString(wordFile, "Laser Focus", 50, "left", true);
            CreateOrOrOpenWordFileInsertString(wordFile, "Laser Beam Focus", 50, "left", true);

            for (int i = 1; i<101; i++)
            {
                System.Drawing.Color color = System.Drawing.Color.FromArgb(255, rnd.Next(0, 255), rnd.Next(0, 255), rnd.Next(0, 255));
                string hexColorStr = ColorToHexString(color);
                CreateOrOrOpenWordFileInsertString(wordFile, $"{i}_{Guid.NewGuid().ToString("N")}"
                    , rnd.Next(20, 50), "left", rnd.Next(0, 10)/2==0, hexColorStr);
            }
        }

        static void CreateOrOrOpenWordFileInsertString(string wordFile, string str, int fontSize = 20,
            string alignment = "left", bool isBold = false, string color = "000000")
        {
            if (!File.Exists(wordFile))
            {
                using (WordprocessingDocument doc = WordprocessingDocument.Create(wordFile, WordprocessingDocumentType.Document))
                {
                    MainDocumentPart mainPart = doc.AddMainDocumentPart();
                    mainPart.Document = new Document(new Body());

                    WriteStringToDoc(mainPart, str, fontSize, alignment, isBold, color);
                    SetWordPageMaximize(mainPart);
                    SetWordPageSize(mainPart);
                }
            }
            else
            {
                using (WordprocessingDocument doc = WordprocessingDocument.Open(wordFile, true))
                {
                    MainDocumentPart mainPart = doc.MainDocumentPart;
                    if (mainPart?.Document?.Body==null)
                    {
                        mainPart.Document=new Document(new Body());
                    }
                    WriteStringToDoc(mainPart, str, fontSize, alignment, isBold, color);
                    SetWordPageMaximize(mainPart);
                    SetWordPageSize(mainPart);
                }
            }
        }

        private static void SetWordPageSize(MainDocumentPart mainPart)
        {
            SectionProperties sectionProps = new SectionProperties(
            new PageSize()
            {
                Width = A0Width,   // A0 width in twips
                Height = A0Height,  // A0 height in twips
                Orient = PageOrientationValues.Landscape
            },
            new PageMargin()
            {
                Top = 1440,    // 1 inch
                Bottom = 1440,
                Left = 1440,
                Right = 1440
            }
        );
            Body body = mainPart.Document.Body;
            body.Append(sectionProps);
            mainPart.Document.Save();
        }

        private static void SetWordPageMaximize(MainDocumentPart mainPart)
        {
            var settingsPart = mainPart.DocumentSettingsPart ?? mainPart.AddNewPart<DocumentSettingsPart>();
            if (settingsPart.Settings == null)
                settingsPart.Settings = new Settings();

            // Remove old zoom/view if exist
            settingsPart.Settings.RemoveAllChildren<Zoom>();
            settingsPart.Settings.RemoveAllChildren<View>();

            // Add new
            settingsPart.Settings.Append(new View() { Val = ViewValues.Print });
            settingsPart.Settings.Append(new Zoom() { Percent = "100" });

            settingsPart.Settings.Save();
        }

        static void WriteStringToDoc(MainDocumentPart mainPart, string str, int fontSize = 20,
            string alignment = "left", bool isBold = false, string color = "000000",
           string fontFamily = "Arial", bool isItalic = false, bool isUnderline = false)
        {
            Body body = mainPart.Document.Body;

            Run run = new Run();
            RunProperties runProperties = new RunProperties();

            // Set font properties
            SetRunProperties(runProperties, fontSize, isBold, isItalic, isUnderline, fontFamily, color);

            // Add properties to run
            if (runProperties.HasChildren)
            {
                run.RunProperties = runProperties;
            }

            // Add text to run             
            run.Append(new Text(str));
            run.Append(new Break());
            Paragraph para = new Paragraph(run);
            SetParagraphAlignment(para, alignment);
            // Add run to paragraph
            body.Append(para);
            mainPart.Document.Save();
        }

        private static void SetRunProperties(RunProperties runProperties, int fontSize,
            bool isBold, bool isItalic, bool isUnderline, string fontFamily, string color)
        {
            runProperties.Append(new FontSize()
            {
                Val = (fontSize * 2).ToString()
            });

            if (isBold)
            {
                runProperties.Append(new Bold());
            }

            if (isItalic)
            {
                runProperties.Append(new Italic());
            }

            if (isUnderline)
            {
                runProperties.Append(new Underline()
                {
                    Val = UnderlineValues.Single
                });
            }

            runProperties.Append(new RunFonts()
            {
                Ascii = fontFamily,
                HighAnsi = fontFamily
            });

            runProperties.Append(new DocumentFormat.OpenXml.Wordprocessing.Color()
            {
                Val = color
            });
        }

        private static void SetParagraphAlignment(Paragraph paragraph, string alignment)
        {
            ParagraphProperties paragraphProps = new ParagraphProperties();
            switch (alignment.ToLower())
            {
                case "center":
                    paragraphProps.Append(new Justification()
                    {
                        Val = JustificationValues.Center
                    });
                    break;

                case "right":
                    paragraphProps.Append(new Justification()
                    {
                        Val = JustificationValues.Right
                    });
                    break;

                case "both":
                    paragraphProps.Append(new Justification()
                    {
                        Val = JustificationValues.Both
                    });
                    break;

                default:
                    paragraphProps.Append(new Justification()
                    {
                        Val = JustificationValues.Left
                    });
                    break;
            }

            paragraph.ParagraphProperties = paragraphProps;
        }

        private static string ColorToHexString(System.Drawing.Color color)
        {
            // Convert to 6-digit hex string (without alpha)
            return $"{color.R:X2}{color.G:X2}{color.B:X2}";
        }  
         
        public static void InsertImagesListIntoWord(string wordFile, List<string> imagePathsList)
        {
            if (!File.Exists(wordFile))
            {
                // Create a new Word document
                using (WordprocessingDocument doc = WordprocessingDocument.Create(
                    wordFile, WordprocessingDocumentType.Document))
                {
                    // Add main document part
                    MainDocumentPart mainPart = doc.AddMainDocumentPart();
                    Body body = new Body();
                    mainPart.Document = new Document(body);

                    InsertImagesInWord(mainPart, imagePathsList);
                }
            }
            else
            {
                using (WordprocessingDocument doc = WordprocessingDocument.Open(wordFile, true))
                {
                    MainDocumentPart mainPart = doc.MainDocumentPart;
                    if (mainPart?.Document?.Body==null)
                    {
                        mainPart.Document=new Document(new Body());
                    }
                    InsertImagesInWord(mainPart, imagePathsList);
                }
            }
        }

        private static void InsertImagesInWord(MainDocumentPart mainPart, List<string> imagePathsList)
        {
            // Add styles part for better formatting
            AddStylesPart(mainPart);

            // Add title
            AddTitle(mainPart, "Document with Images");

            // Insert each image
            foreach (var imagePath in imagePathsList)
            {
                AddImageWithCaption(mainPart, imagePath);
                Console.WriteLine(imagePath);
            }

            //Word’s page size units are in twips(1/20th of a point).
            //A0 = 841 × 1189 mm = 33.1 × 46.8 inches
            //1 inch = 1440 twips
            //So:
            //Width = 33.1 × 1440 ≈ 47664 twips
            //Height = 46.8 × 1440 ≈ 67456 twips
            // Add required SectionProperties with A0 page size
            SectionProperties sectionProps = new SectionProperties(
                new PageSize()
                {
                    Width = A0Width,   // A0 width in twips
                    Height = A0Height,  // A0 height in twips
                    Orient = PageOrientationValues.Landscape
                },
                new PageMargin()
                {
                    Top = 1440,    // 1 inch
                    Bottom = 1440,
                    Left = 1440,
                    Right = 1440
                }
            );

            Body body = mainPart.Document.Body;
            body.Append(sectionProps);
            mainPart.Document.Save();
        }

        private static void AddStylesPart(MainDocumentPart mainPart)
        {
            StyleDefinitionsPart stylePart = mainPart.AddNewPart<StyleDefinitionsPart>();
            Styles styles = new Styles();

            // Add some basic styles
            styles.Append(CreateParagraphStyle("Title", "Title", "36"));
            styles.Append(CreateParagraphStyle("Heading1", "Heading 1", "24"));
            styles.Append(CreateParagraphStyle("Normal", "Normal", "12"));

            stylePart.Styles = styles;
        }

        private static Style CreateParagraphStyle(string styleId, string styleName, string fontSize)
        {
            return new Style()
            {
                Type = StyleValues.Paragraph,
                StyleId = styleId,
                CustomStyle = true,
                StyleName = new StyleName() { Val = styleName },
                StyleParagraphProperties = new StyleParagraphProperties(
                    new SpacingBetweenLines() { After = "200" }),
                StyleRunProperties = new StyleRunProperties(
                    new FontSize() { Val = fontSize })
            };
        }

        private static void AddTitle(MainDocumentPart mainPart, string titleText)
        {
            Paragraph titleParagraph = new Paragraph(
                new ParagraphProperties(
                    new ParagraphStyleId() { Val = "Title" }),
                new Run(
                    new RunProperties(
                        new FontSize() { Val="100" }),
                    new Text(titleText)));

            mainPart.Document.Body.AppendChild(titleParagraph);
        }

        private static void AddImageWithCaption(MainDocumentPart mainPart, string imagePath)
        {
            long widthEmu, heightEmu;
            using (var image = System.Drawing.Image.FromFile(imagePath))
            {
                const int emusPerInch = 914400;
                double widthInches = image.Width/image.HorizontalResolution;
                double heightInches = image.Height/image.VerticalResolution;
                widthEmu=(long)(widthInches*emusPerInch);
                heightEmu= (long)(heightInches*emusPerInch);
            }

            long maxWidth = A0Width * EmusPerInch / 1440;
            long maxHeight = A0Height * EmusPerInch / 1440;

            if (widthEmu > maxWidth || heightEmu > maxHeight)
            {
                double ratio = Math.Min((double)maxWidth / widthEmu,
                                        (double)maxHeight / heightEmu);

                widthEmu = (long)(widthEmu * ratio);
                heightEmu = (long)(heightEmu * ratio);
            }


            // Add image part
            ImagePart imagePart = mainPart.AddImagePart(GetImagePartType(imagePath));
            using (FileStream stream = new FileStream(imagePath, FileMode.Open,
                FileAccess.Read, FileShare.Read))
            {
                imagePart.FeedData(stream);
            }

            string relationshipId = mainPart.GetIdOfPart(imagePart);

            // Create image drawing
            var drawing = CreateImageDrawing(relationshipId, widthEmu, heightEmu,
                                           Path.GetFileName(imagePath));

            // Add image paragraph
            Paragraph imageParagraph = new Paragraph(
                new ParagraphProperties(
                    new Justification() { Val = JustificationValues.Center }),
                new Run(drawing));

            mainPart.Document.Body.AppendChild(imageParagraph);

            // Add caption
            AddCaption(mainPart, $"Image: {Path.GetFileName(imagePath)}");
        }

        private static PartTypeInfo GetImagePartType(string imagePath)
        {
            string extension = Path.GetExtension(imagePath).ToLower();
            return extension switch
            {
                ".jpg" or ".jpeg" => ImagePartType.Jpeg,
                ".png" => ImagePartType.Png,
                ".bmp" => ImagePartType.Bmp,
                ".gif" => ImagePartType.Gif,
                ".tiff" => ImagePartType.Tiff,
                _ => ImagePartType.Jpeg
            };
        }

        private static Drawing CreateImageDrawing(string relationshipId, long width, long height, string imageName)
        {
            return new Drawing(
                new DW.Inline(
                    new DW.Extent() { Cx = width, Cy = height },
                    new DW.EffectExtent()
                    {
                        LeftEdge = 0L,
                        TopEdge = 0L,
                        RightEdge = 0L,
                        BottomEdge = 0L
                    },
                    new DW.DocProperties() { Id = 1U, Name = imageName },
                    new DW.NonVisualGraphicFrameDrawingProperties(
                        new A.GraphicFrameLocks() { NoChangeAspect = true }),
                    new A.Graphic(
                        new A.GraphicData(
                            new PIC.Picture(
                                new PIC.NonVisualPictureProperties(
                                    new PIC.NonVisualDrawingProperties()
                                    {
                                        Id = 0U,
                                        Name = imageName
                                    },
                                    new PIC.NonVisualPictureDrawingProperties()),
                                new PIC.BlipFill(
                                    new A.Blip(
                                        new A.BlipExtensionList(
                                            new A.BlipExtension()
                                            {
                                                Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}"
                                            })
                                    )
                                    {
                                        Embed = relationshipId
                                    },
                                    new A.Stretch(
                                        new A.FillRectangle())),
                                new PIC.ShapeProperties(
                                    new A.Transform2D(
                                        new A.Offset() { X = 0L, Y = 0L },
                                        new A.Extents() { Cx = width, Cy = height }),
                                    new A.PresetGeometry(
                                        new A.AdjustValueList()
                                    )
                                    { Preset = A.ShapeTypeValues.Rectangle }))
                        )
                        { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" })
                )
                {
                    DistanceFromTop = 0U,
                    DistanceFromBottom = 0U,
                    DistanceFromLeft = 0U,
                    DistanceFromRight = 0U
                });
        }

        private static void AddCaption(MainDocumentPart mainPart, string captionText)
        {
            Paragraph captionParagraph = new Paragraph(
                new ParagraphProperties(
                    new ParagraphStyleId() { Val = "Normal" },
                    new Justification() { Val = JustificationValues.Center }),
                new Run(
                    new Text(captionText)));

            mainPart.Document.Body.AppendChild(captionParagraph);

            // Add some space after caption
            mainPart.Document.Body.AppendChild(
                new Paragraph(
                    new ParagraphProperties(
                        new SpacingBetweenLines() { After = "400" })));
        }
    }     
} 

 

 

image

 

 

 

 

 

 

image

 

 

image

 

posted @ 2025-09-05 14:18  FredGrit  阅读(10)  评论(0)    收藏  举报