c# operate tables in word, batch copy and batch insert

The dll package that comes with Windows is used, and no third party is referenced.

1 WordHelper.cs

using System;
using Microsoft.Office.Interop.Word;
using System.Runtime.InteropServices;

namespace cadWord
{
    public class WordHelper
    {
        private Microsoft.Office.Interop.Word.Document wDoc = null;
        private Microsoft.Office.Interop.Word.Application wApp = null;
        public Microsoft.Office.Interop.Word.Document Document
        {
            get { return wDoc; }
            set { wDoc = value; }
        }

        public Microsoft.Office.Interop.Word.Application Application
        {
            get { return wApp; }
            set { wApp = value; }
        }
        /// <summary>
        /// Open the specified WORD document
        /// </summary>
        /// <param name="strFileName"></param>
        public void Open(string strFileName)
        {
            wApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            object fileName = strFileName;
            object readOnly = false;
            object isVisible = true;
            object missing = Type.Missing;
            wDoc = wApp.Documents.Open(ref fileName, ref missing, ref readOnly,
                ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref isVisible, ref missing, ref missing, ref missing, ref missing);

            wDoc.Activate();
        }

        #region Create a new Word document from a template
        /// <summary>
        /// Create a new Word document from a template
        /// </summary>
        /// <param name="templateName">Template file name</param>
        /// <returns></returns>
        public bool CreateNewWordDocument(string templateName)
        {
            try
            {
                return CreateNewWordDocument(templateName, ref wDoc, ref wApp);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region creates a new Word document from the template and returns the object Document, Application
        /// <summary>
        /// Create a new Word document from a template,
        /// </summary>
        /// <param name="templateName">Template file name</param>
        /// <param name="wDoc">The returned Word.Document object</param>
        /// <param name="WApp">The returned Word.Application object</param>
        /// <returns></returns>
        public static bool CreateNewWordDocument(string templateName, ref Microsoft.Office.Interop.Word.Document wDoc, ref Microsoft.Office.Interop.Word.Application WApp)
        {
            Microsoft.Office.Interop.Word.Document thisDocument = null;
            Microsoft.Office.Interop.Word.Application thisApplication = new Microsoft.Office.Interop.Word.Application();/
            thisApplication.Visible = false;
            thisApplication.Caption = "";
            thisApplication.Options.CheckSpellingAsYouType = false;
            thisApplication.Options.CheckGrammarAsYouType = false;

            Object Template = templateName;// Optional Object. The name of the template to be used for the new document. If this argument is omitted, the Normal template is used.
            Object NewTemplate = false;// Optional Object. True to open the document as a template. The default value is False.
            Object DocumentType = Microsoft.Office.Interop.Word.WdNewDocumentType.wdNewBlankDocument; // Optional Object. Can be one of the following WdNewDocumentType constants: wdNewBlankDocument, wdNewEmailMessage, wdNewFrameset, or wdNewWebPage. The default constant is wdNewBlankDocument.
            Object Visible = true;//Optional Object. True to open the document in a visible window. If this value is False, Microsoft Word opens the document but sets the Visible property of the document window to False. The default value is True.

            try
            {
                Microsoft.Office.Interop.Word.Document wordDoc = thisApplication.Documents.Add(ref Template, ref NewTemplate, ref DocumentType, ref Visible);

                thisDocument = wordDoc;
                wDoc = wordDoc;
                WApp = thisApplication;
                return true;
            }
            catch (Exception ex)
            {
                string err = string.Format("Error in creating Word document, error reason: {0}", ex.Message);
                throw new Exception(err, ex);
            }
        }
        #endregion

        #region Document saved as a different file name
        /// <summary>
        /// Save the document as another file name
        /// </summary>
        /// <param name="fileName">File name</param>
        /// <param name="wDoc">Document object</param>
        public bool SaveAs(string fileName)
        {
            try
            {
                return SaveAs(fileName, wDoc);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Document saved as a different file name
        /// <summary>
        /// Save the document as another file name
        /// </summary>
        /// <param name="fileName">File name</param>
        /// <param name="wDoc">Document object</param>
        public static bool SaveAs(string fileName, Microsoft.Office.Interop.Word.Document wDoc)
        {
            Object FileName = fileName; //The name of the document. The default values are the current folder name and file name. If the document has not been saved before, the default name is used (for example, Doc1.doc). If a document with the specified file name already exists, the document is overwritten without first prompting the user.
            Object FileFormat = Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatDocument; // The saving format of the document. Can be any WdSaveFormat value. To save the document in another format, specify the appropriate value for the SaveFormat property.
            Object LockComments = false; // If true, locks the document for comments. The default value is false.
            Object Password = System.Type.Missing; // Password string used to open the document. (See notes below.)
            Object AddToRecentFiles = false; // If true, adds the document to the recent files list on the File menu. The default value is true.
            Object WritePassword = System.Type.Missing; // The password string used to save changes to the file. (See notes below.)
            Object ReadOnlyRecommended = false; // If true, causes Microsoft Office Word to recommend read-only status when opening the document. The default value is false.
            Object EmbedTrueTypeFonts = false; //If true, TrueType fonts are saved with the document. If omitted, the EmbedTrueTypeFonts parameter assumes the value of the EmbedTrueTypeFonts property.
            Object SaveNativePictureFormat = true; // If the graphic was imported from another platform (for example, Macintosh), true means only the Windows version of the imported graphic will be saved.
            Object SaveFormsData = false; // If true, save the data entered by the user in the form as a data record.
            Object SaveAsAOCELetter = false; // If the document has a mailer attached, true means the document will be saved as an AOCEL letter (the mailer will save it).
            Object Encoding = System.Type.Missing; // MsoEncoding. The code page or character set to use for documents saved as encoded text files. The default value is the system code page.
            Object InsertLineBreaks = true; // If the document is saved as a text file, true means inserting line breaks at the end of each line of text.
            Object AllowSubstitutions = false; //If the document is saved as a text file, true allows Word to replace certain symbols with text that looks similar to it. For example, display the copyright symbol as (c). The default value is false.
            Object LineEnding = Microsoft.Office.Interop.Word.WdLineEndingType.wdCRLF; // Word marks line breaks and paragraph breaks in documents saved as text files. Can be any WdLineEndingType value.
            Object AddBiDiMarks = true; //If true, add control characters to the output file to preserve the bidirectional layout of the text in the original document.
            try
            {
                wDoc.SaveAs(ref FileName, ref FileFormat, ref LockComments, ref Password, ref AddToRecentFiles, ref WritePassword
                        , ref ReadOnlyRecommended, ref EmbedTrueTypeFonts, ref SaveNativePictureFormat
                        , ref SaveFormsData, ref SaveAsAOCELetter, ref Encoding, ref InsertLineBreaks, ref AllowSubstitutions
                        , ref LineEnding, ref AddBiDiMarks);
                return true;

            }
            catch (Exception ex)
            {
                string err = string.Format("Error saving file, error reason: {0}", ex.Message);
                throw new Exception(err, ex);
            }
        }
        #endregion

        #region Close document
        /// <summary>
        /// Close document
        /// </summary>
        public void Close()
        {
            Close(wDoc, wApp);
            wDoc = null;
            wApp = null;
        }
        #endregion
        [DllImport("shell32.dll ")]
        public static extern int ShellExecute(IntPtr hwnd, String lpszOp, String lpszFile, String lpszParams, String lpszDir, int FsShowCmd);
        #region Close document
        /// <summary>
        /// Close document
        /// </summary>
        /// <param name="wDoc">Document object</param>
        /// <param name="WApp">Application object</param>
        public static void Close(Microsoft.Office.Interop.Word.Document wDoc, Microsoft.Office.Interop.Word.Application WApp)
        {

            Object SaveChanges = Microsoft.Office.Interop.Word.WdSaveOptions.wdSaveChanges;//Specify the save operation of the document. Can be one of the following WdSaveOptions values: wdDoNotSaveChanges, wdPromptToSaveChanges, or wdSaveChanges.
            Object OriginalFormat = Microsoft.Office.Interop.Word.WdOriginalFormat.wdOriginalDocumentFormat;//Specify the saving format of the document. Can be one of the following WdOriginalFormat values: wdOriginalDocumentFormat, wdPromptUser, or wdWordDocument.
            Object RouteDocument = false; // If true, the document is delivered to the next recipient. If no delivery list is attached to the document, this parameter is ignored.
            try
            {
                if (wDoc != null) wDoc.Close(ref SaveChanges, ref OriginalFormat, ref RouteDocument);
                if (WApp != null) WApp.Quit(ref SaveChanges, ref OriginalFormat, ref RouteDocument);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        #endregion

        #region Populate bookmarks
        /// <summary>
        /// Fill in bookmarks
        /// </summary>
        /// <param name="bookmark">Bookmark</param>
        /// <param name="value">value</param>
        public void Replace(string bookmark, string value)
        {
            try
            {
                object bkObj = bookmark;
                if (wApp.ActiveDocument.Bookmarks.Exists(bookmark) == true)
                {
                    wApp.ActiveDocument.Bookmarks.get_Item(ref bkObj).Select();
                }
                else return;
                wApp.Selection.TypeText(value);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        public bool FindTable(string bookmarkTable)
        {
            try
            {
                object bkObj = bookmarkTable;
                if (wApp.ActiveDocument.Bookmarks.Exists(bookmarkTable) == true)
                {
                    wApp.ActiveDocument.Bookmarks.get_Item(ref bkObj).Select();
                    return true;
                }
                else
                    return false;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void MoveNextCell()
        {
            try
            {
                Object unit = Microsoft.Office.Interop.Word.WdUnits.wdCell;
                Object count = 1;
                wApp.Selection.Move(ref unit, ref count);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void tableInsertRows(int i, int j, int count, int k)
        {
            Microsoft.Office.Interop.Word.Table newTable = wDoc.Tables[k];
            for (int jj = 0; jj < count; jj + + )
            {
                object beforeRow = newTable.Cell(i, j).Range;
                newTable.Rows.Add(ref beforeRow);
            }
        }

        public void SetWordCellValue(int i, int j, int k, string value)
        {
            try
            {
                Microsoft.Office.Interop.Word.Table newTable = wDoc.Tables[k];
                newTable.Cell(i, j).Range.Text = value;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// Insert picture
        /// </summary>
        /// <param name="i"></param>
        /// <param name="j"></param>
        /// <param name="k"></param>
        /// <param name="strPicPath"></param>
        public void InsertImage(int i, int j, int k, string strPicPath)
        {
            Microsoft.Office.Interop.Word.Table newTable = wDoc.Tables[k];
            string FileName = strPicPath;
            object LinkToFile = false;
            object SaveWithDocument = true;
            object Anchor = newTable.Cell(i, j).Range;
            wApp.ActiveDocument.InlineShapes.AddPicture(FileName, ref LinkToFile, ref SaveWithDocument, ref Anchor).Select();

        }

        public void SetCellValue(string value)
        {
            try
            {
                wApp.Selection.Rows.Alignment = WdRowAlignment.wdAlignRowCenter;
                wApp.Selection.TypeText(value);
                wApp.Selection.Rows.Alignment = WdRowAlignment.wdAlignRowCenter;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetCellValue()
        {
            try
            {

                string value = wApp.Selection.Text;
                if (value.Length <= 2)
                {

                    return "";
                }
                else
                    return value;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void MoveNextRow()
        {
            try
            {
                Object extend = Microsoft.Office.Interop.Word.WdMovementType.wdExtend;
                Object unit = Microsoft.Office.Interop.Word.WdUnits.wdCell;
                Object count = 1;
                wApp.Selection.MoveRight(ref unit, ref count, ref extend);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        //Get the text content of the word file
        public string DocToText(string docFileName, out Font xx)
        {
            //instantiate COM
            Application Word_App = new Application();/
            object fileobj = docFileName;
            object nullobj = System.Reflection.Missing.Value;//Open the specified file (the number of COM parameters varies in different versions,
            //Generally speaking, just use nulllobj except for the first one)


            Document wd = Word_App.Documents.Open(ref fileobj, ref nullobj, ref nullobj, ref nullobj,
                                                    ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj,
                                                    ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj,
                                                    ref nullobj, ref nullobj);
            //Get the text content in the doc file
            string outText = wd.Content.Text;
            xx = wd.Content.Font;
            //Close file
            wd.Close(ref nullobj, ref nullobj, ref nullobj);
            //Close COM
            Word_App.Quit(ref nullobj, ref nullobj, ref nullobj);
            //return text content
            return outText;
        }



        /// <summary>
        /// Copy the tables already stored in the template and generate an indefinite number of tables at subsequent locations.
        /// </summary>
        /// <param name="_tableIndex">Object table</param>
        /// <param name="_row">The position after the table, that is, calculating the number of rows and rows can also calculate the number</param>
        /// <param name="_tableNum">Number of tables</param>
        public void copyTableInsert(int _tableIndex, object _row, int _tableNum)
        {
            //--start-#According to the table serial number index, obtain the object table#-->
            Microsoft.Office.Interop.Word.Table copyTable = wDoc.Tables[_tableIndex];
            //--start-#Copy the object table#-->
            copyTable.Range.Copy();//Copy it
            //--start-#Let the cursor select the object table#-->
            copyTable.Select();
            //--start-#Do not allow table to break rows across pages#-->
            copyTable.AllowPageBreaks = false;

            object what = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToLine;
            object which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToNext;
            object missing = Type.Missing;
            //--start-#Move the cursor to the back of the table#-->
            wApp.Selection.GoTo(ref what, ref which, ref _row, ref missing);
            //--start-#Calculate the number of generated tables#-->
            for (int i = 0; i < _tableNum; i + + )
            {
                //--start-#Insert page break after table#-->
                wApp.Selection.InsertBreak(ref missing);
                //--start-#Copy table generation#-->
                wApp.Selection.Paste();
            }










            // Microsoft.Office.Interop.Word.Table copyTable = wDoc.Tables[3];
            // copyTable.Range.Copy();//Copy it
            // copyTable.Select();//Select the table object, and the cursor is already on this table.
            // copyTable.AllowPageBreaks = false;

            // //The first table after copying: Laboratory 2
            // object what = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToLine;
            // object which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToNext;
            // object missing = Type.Missing;

            // // object count = 36; // Cursor moves down 3 spaces
            // wApp.Selection.GoTo(ref what, ref which, ref _row, ref missing);
            // // wApp.Selection.Range.Text = "Single Building Verification Comparison Table 2\\
"; //Insert text
            // wApp.Selection.GoTo(ref what, ref which, 1, ref missing); //Move the cursor down 1 space, if it is not with the text of the department being tested, start a new line
            // wApp.Selection.Paste();//Paste table



            // //The first table after copying: Laboratory 2

            // //what = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToLine;
            // //which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToNext;
             wApp.Selection.Range.Text = "Tested department: Laboratory 2\\
";//Insert text

            // wApp.Selection.GoTo(ref what, ref which, 1, ref missing); //Move the cursor down 1 space, if it is not with the text of the department being tested, start a new line
            // wApp.Selection.Paste();//Paste table
        }

    }
}

2 Core code

 /// <summary>
        /// Copy the tables already stored in the template and generate an indefinite number of tables at subsequent locations.
        /// </summary>
        /// <param name="_tableIndex">Object table</param>
        /// <param name="_row">The position after the table, that is, calculating the number of rows and rows can also calculate the number</param>
        /// <param name="_tableNum">Number of tables</param>
        public void copyTableInsert(int _tableIndex, object _row, int _tableNum)
        {
            //--start-#According to the table serial number index, obtain the object table#-->
            Microsoft.Office.Interop.Word.Table copyTable = wDoc.Tables[_tableIndex];
            //--start-#Copy the object table#-->
            copyTable.Range.Copy();//Copy it
            //--start-#Let the cursor select the object table#-->
            copyTable.Select();
            //--start-#Do not allow table to break rows across pages#-->
            copyTable.AllowPageBreaks = false;

            object what = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToLine;
            object which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToNext;
            object missing = Type.Missing;
            //--start-#Move the cursor to the back of the table#-->
            wApp.Selection.GoTo(ref what, ref which, ref _row, ref missing);
            //--start-#Calculate the number of generated tables#-->
            for (int i = 0; i < _tableNum; i + + )
            {
                //--start-#Insert page break after table#-->
                wApp.Selection.InsertBreak(ref missing);
                //--start-#Copy table generation#-->
                wApp.Selection.Paste();
            }










            // Microsoft.Office.Interop.Word.Table copyTable = wDoc.Tables[3];
            // copyTable.Range.Copy();//Copy it
            // copyTable.Select();//Select the table object, and the cursor is already on this table.
            // copyTable.AllowPageBreaks = false;

            // //The first table after copying: Laboratory 2
            // object what = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToLine;
            // object which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToNext;
            // object missing = Type.Missing;

            // // object count = 36; // Cursor moves down 3 spaces
            // wApp.Selection.GoTo(ref what, ref which, ref _row, ref missing);
            // // wApp.Selection.Range.Text = "Single Building Verification Comparison Table 2\\
"; //Insert text
            // wApp.Selection.GoTo(ref what, ref which, 1, ref missing); //Move the cursor down 1 space, if it is not with the text of the department being tested, start a new line
            // wApp.Selection.Paste();//Paste table



            // //The first table after copying: Laboratory 2

            // //what = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToLine;
            // //which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToNext;
             wApp.Selection.Range.Text = "Tested department: Laboratory 2\\
";//Insert text

            // wApp.Selection.GoTo(ref what, ref which, 1, ref missing); //Move the cursor down 1 space, if it is not with the text of the department being tested, start a new line
            // wApp.Selection.Paste();//Paste table
        }

3 Calling code

After inserting tables in batches, the principle is that the entire document will be indexed from front to back. From the beginning, it means that the front serial number is table 1.2.3, 1 is copied 3 at the back, then the original 2 table serial number is marked as 2 + 3= 5! Setting various values for the table is also based on this serial number!

 private void button1_Click(object sender, EventArgs e)
        {
            string mbPath = System.IO.Path.Combine(Application.StartupPath + "\MB", "Measurement report sample.docx");//Template

            string savePath = @"C:\Users\54061\Desktop\333\test\measurement report sample.docx";//Save path


            //string imagePath = @"C:\Users\54061\Desktop\Peng Zejun\test\Jiangxi Engineering Co., Ltd. (official seal).png";//Save path
            File.Copy(mbPath, savePath, true);

            WordHelper wordhelper = new WordHelper();
            wordhelper.Open(savePath);

            //--start-#Calculation generated table#-->
            wordhelper.copyTableInsert(3, 32, 5);
            wordhelper.copyTableInsert(4 + 5, 4, 5);
            wordhelper.copyTableInsert(5 + 5 + 5, 14, 5);
            //--start-#Calculate single building verification comparison table#-->
         
            wordhelper.Close();
            MessageBox.Show("Export completed!");
        }