C#生成word的几种方式。过程及问题记录。

最近接到了一个小任务:使用word将数据输出,datatable也好datagridview也罢,生成才是第一要义。

一、

首先肯定是在网上找资料了,然后找到一个微软官方解释说明文档,特别好。

如何: 使用 Visual c # 自动化 Microsoft Word 创建新文档

本分步指南介绍了如何使用 Microsoft Visual c # 2005 或 Microsoft Visual c # .NET 中的自动化功能在 Microsoft Word 中创建新文档。

 

  • 本文中的示例代码演示了如何执行以下操作:

    若要使用 Visual c # 2005 或 Visual c # .NET 中的自动化功能创建新的 Word 文档, 请按照以下步骤操作:

    • 插入包含文本和格式的段落。
    • 浏览和修改文档中的各种区域。
    • 插入表格、设置表格格式并使用数据填充表格。
    • 添加图表。
  • 代码完成后, 检查为您创建的文档。 该文档包含两页的格式段落、表格和图表

  • 单击 "Button1" 以启动 Word Automation 并创建文档。

  • 按 F5 生成并运行该程序。

  • private void button1_Click(object sender, System.EventArgs e)
    {
    object oMissing = System.Reflection.Missing.Value;
    object oEndOfDoc = "\\endofdoc"; /* \endofdoc is a predefined bookmark */ 
    
    //Start Word and create a new document.
    Word._Application oWord;
    Word._Document oDoc;
    oWord = new Word.Application();
    oWord.Visible = true;
    oDoc = oWord.Documents.Add(ref oMissing, ref oMissing,
    ref oMissing, ref oMissing);
    
    //Insert a paragraph at the beginning of the document.
    Word.Paragraph oPara1;
    oPara1 = oDoc.Content.Paragraphs.Add(ref oMissing);
    oPara1.Range.Text = "Heading 1";
    oPara1.Range.Font.Bold = 1;
    oPara1.Format.SpaceAfter = 24;    //24 pt spacing after paragraph.
    oPara1.Range.InsertParagraphAfter();
    
    //Insert a paragraph at the end of the document.
    Word.Paragraph oPara2;
    object oRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
    oPara2 = oDoc.Content.Paragraphs.Add(ref oRng);
    oPara2.Range.Text = "Heading 2";
    oPara2.Format.SpaceAfter = 6;
    oPara2.Range.InsertParagraphAfter();
    
    //Insert another paragraph.
    Word.Paragraph oPara3;
    oRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
    oPara3 = oDoc.Content.Paragraphs.Add(ref oRng);
    oPara3.Range.Text = "This is a sentence of normal text. Now here is a table:";
    oPara3.Range.Font.Bold = 0;
    oPara3.Format.SpaceAfter = 24;
    oPara3.Range.InsertParagraphAfter();
    
    //Insert a 3 x 5 table, fill it with data, and make the first row
    //bold and italic.
    Word.Table oTable;
    Word.Range wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
    oTable = oDoc.Tables.Add(wrdRng, 3, 5, ref oMissing, ref oMissing);
    oTable.Range.ParagraphFormat.SpaceAfter = 6;
    int r, c;
    string strText;
    for(r = 1; r <= 3; r++)
    for(c = 1; c <= 5; c++)
    {
    strText = "r" + r + "c" + c;
    oTable.Cell(r, c).Range.Text = strText;
    }
    oTable.Rows[1].Range.Font.Bold = 1;
    oTable.Rows[1].Range.Font.Italic = 1;
    
    //Add some text after the table.
    Word.Paragraph oPara4;
    oRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
    oPara4 = oDoc.Content.Paragraphs.Add(ref oRng);
    oPara4.Range.InsertParagraphBefore();
    oPara4.Range.Text = "And here's another table:";
    oPara4.Format.SpaceAfter = 24;
    oPara4.Range.InsertParagraphAfter();
    
    //Insert a 5 x 2 table, fill it with data, and change the column widths.
    wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
    oTable = oDoc.Tables.Add(wrdRng, 5, 2, ref oMissing, ref oMissing);
    oTable.Range.ParagraphFormat.SpaceAfter = 6;
    for(r = 1; r <= 5; r++)
    for(c = 1; c <= 2; c++)
    {
    strText = "r" + r + "c" + c;
    oTable.Cell(r, c).Range.Text = strText;
    }
    oTable.Columns[1].Width = oWord.InchesToPoints(2); //Change width of columns 1 & 2
    oTable.Columns[2].Width = oWord.InchesToPoints(3);
    
    //Keep inserting text. When you get to 7 inches from top of the
    //document, insert a hard page break.
    object oPos;
    double dPos = oWord.InchesToPoints(7);
    oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range.InsertParagraphAfter();
    do
    {
    wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
    wrdRng.ParagraphFormat.SpaceAfter = 6;
    wrdRng.InsertAfter("A line of text");
    wrdRng.InsertParagraphAfter();
    oPos = wrdRng.get_Information
                           (Word.WdInformation.wdVerticalPositionRelativeToPage);
    }
    while(dPos >= Convert.ToDouble(oPos));
    object oCollapseEnd = Word.WdCollapseDirection.wdCollapseEnd;
    object oPageBreak = Word.WdBreakType.wdPageBreak;
    wrdRng.Collapse(ref oCollapseEnd);
    wrdRng.InsertBreak(ref oPageBreak);
    wrdRng.Collapse(ref oCollapseEnd);
    wrdRng.InsertAfter("We're now on page 2. Here's my chart:");
    wrdRng.InsertParagraphAfter();
    
    //Insert a chart.
    Word.InlineShape oShape;
    object oClassType = "MSGraph.Chart.8";
    wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
    oShape = wrdRng.InlineShapes.AddOLEObject(ref oClassType, ref oMissing, 
    ref oMissing, ref oMissing, ref oMissing,
    ref oMissing, ref oMissing, ref oMissing);
    
    //Demonstrate use of late bound oChart and oChartApp objects to
    //manipulate the chart object with MSGraph.
    object oChart;
    object oChartApp;
    oChart = oShape.OLEFormat.Object;
    oChartApp = oChart.GetType().InvokeMember("Application",
    BindingFlags.GetProperty, null, oChart, null);
    
    //Change the chart type to Line.
    object[] Parameters = new Object[1];
    Parameters[0] = 4; //xlLine = 4
    oChart.GetType().InvokeMember("ChartType", BindingFlags.SetProperty,
    null, oChart, Parameters);
    
    //Update the chart image and quit MSGraph.
    oChartApp.GetType().InvokeMember("Update",
    BindingFlags.InvokeMethod, null, oChartApp, null);
    oChartApp.GetType().InvokeMember("Quit",
    BindingFlags.InvokeMethod, null, oChartApp, null);
    //... If desired, you can proceed from here using the Microsoft Graph 
    //Object model on the oChart and oChartApp objects to make additional
    //changes to the chart.
    
    //Set the width of the chart.
    oShape.Width = oWord.InchesToPoints(6.25f);
    oShape.Height = oWord.InchesToPoints(3.57f);
    
    //Add text after the chart.
    wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
    wrdRng.InsertParagraphAfter();
    wrdRng.InsertAfter("THE END.");
    
    //Close this form.
    this.Close();
    }
    

     

  • 滚动到 "代码" 窗口的顶部。 将以下行添加到 using 指令列表的末尾:
    using Word = Microsoft.Office.Interop.Word;
    using System.Reflection;

  • 注释在 Visual Studio 2005 中, 不必单击 "选择"。

    注释Microsoft Office 2003 包括主互操作程序集 (Pia)。 Microsoft Office XP 不包含 Pia, 但可以下载它们。

    1. 在"项目"菜单上单击"添加引用"。
    2. 在 "COM" 选项卡上, 找到 "Microsoft Word 对象库", 然后单击 "选择"。
    3. 单击 "添加引用" 对话框中的 "确定" 以接受您的选择。 如果系统提示您为选定的库生成包装, 请单击 "是"

 很详细,直接根据说明写就行,然后就能生成了。将固定数据h转换成自己想要输入的动态数据就行。

问题:使用打他tabale没有任何问题,但是换成datagridview强转成的datatable就得不到数据不知道咋回事(我已经绑定数据源了),不使用强转的话可以将datagridview便利到datatable中然后获取数,但我觉得转化麻烦,不知道为啥

转化公式:

1.如已绑定过数据源:DataTable dt = (dataGridView1.DataSource as DataTable)

2.如未绑定过数据源:

public DataTable GetDgvToTable(DataGridView dgv)
        {
            DataTable dt = new DataTable();

            // 列强制转换
            for (int count = 0; count < dgv.Columns.Count; count++)
            {
                DataColumn dc = new DataColumn(dgv.Columns[count].Name.ToString());
                dt.Columns.Add(dc);
            }

            // 循环行
            for (int count = 0; count < dgv.Rows.Count; count++)
            {
                DataRow dr = dt.NewRow();
                for (int countsub = 0; countsub < dgv.Columns.Count; countsub++)
                {
                    dr[countsub] = Convert.ToString(dgv.Rows[count].Cells[countsub].Value);
                }
                dt.Rows.Add(dr);
            }
            return dt;
        }

直接可用。

然后东西暂时生成了,但是样式,格式等可能都不是你想要的样子,在实际生产环境中,可能你需要将数据填充入固定模板中,所以可以使用以下方法,

第二种方式:首先建一个word模板,将要word插入数据的地方插入标签,将模板保存为dotx格式,在源代码中

    private void btnword2_Click(object sender, EventArgs e)
        {
            //*************
            object oMissing = System.Reflection.Missing.Value;
            //创建一个Word应用程序实例
            Microsoft.Office.Interop.Word._Application oWord = new Microsoft.Office.Interop.Word.Application();
            //设置为不可见
            oWord.Visible = false;
            //模板文件地址,这里假设在X盘根目录
            object oTemplate =Application.StartupPath+ "\\Template.dotx";
            //以模板为基础生成文档
            Microsoft.Office.Interop.Word._Document oDoc = oWord.Documents.Add(ref oTemplate, ref oMissing, ref oMissing, ref oMissing);
            //加格式
            //object oStyleName = "MyStyle";
            //oDoc.Bookmarks.get_Item(ref oBookMark).Range.set_Style(ref oStyleName);        //声明书签数组
            object[] oBookMark = new object[6];
            //赋值书签名
            oBookMark[0] = "lie1";
            oBookMark[1] = "lie2";
            oBookMark[2] = "lie3";
            oBookMark[3] = "lie4";
            oBookMark[4] = "lie5";
            oBookMark[5] = "lie6";
           // oBookMark[6] = "lie7";
            //赋值任意数据到书签的位置
            oDoc.Bookmarks.get_Item(ref oBookMark[0]).Range.Text = "Word生成";
            oDoc.Bookmarks.get_Item(ref oBookMark[1]).Range.Text = "李四";
            oDoc.Bookmarks.get_Item(ref oBookMark[2]).Range.Text = "女";
            oDoc.Bookmarks.get_Item(ref oBookMark[3]).Range.Text = "1999";
            oDoc.Bookmarks.get_Item(ref oBookMark[4]).Range.Text = "北京";
            oDoc.Bookmarks.get_Item(ref oBookMark[5]).Range.Text = "诗经山";
           //oDoc.Bookmarks.get_Item(ref oBookMark[6]).Range.Text = "贺州";
            //弹出保存文件对话框,保存生成的Word
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "Word Data(*.doc)|*.doc";
            sfd.DefaultExt = "Word Data(*.doc)|*.doc";
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                object filename = sfd.FileName;

                oDoc.SaveAs(ref filename, ref oMissing, ref oMissing, ref oMissing,
                ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
                ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
                ref oMissing, ref oMissing);
                oDoc.Close(ref oMissing, ref oMissing, ref oMissing);
                //关闭word
                oWord.Quit(ref oMissing, ref oMissing, ref oMissing);
                this.txtMessage.Text = "导出成功";
            }

        }

注意模板地址和模板中标签签名要和代码中一致,生成即可。

第三、使用Aspose.Words 插件。这个插件的好处是,发布网站的服务不需要安装office,也可以进行数据生成word文档

在生成word问当前需要我们先做好一个word模板,需要在“:”后边添加一个书签 

注意:Aspose插件,有的版本不支持生成后缀为 .docx的模板,否则提示文档损坏

string tmppath = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory + "/DocTemp/createuser.doc");
                Document doc = new Document(tmppath); //载入模板      
                Bookmark name = doc.Range.Bookmarks["name"];
                name.Text = model.Name;
                Bookmark account = doc.Range.Bookmarks["account"];
                account.Text = model.Account;
                Bookmark password = doc.Range.Bookmarks["password"];
                password.Text = model.PassWord;
                Bookmark sex = doc.Range.Bookmarks["sex"];
                sex.Text = model.Sex;
                Bookmark height = doc.Range.Bookmarks["height"];
                height.Text = model.Height;

                Bookmark weight = doc.Range.Bookmarks["weight"];
                weight.Text = model.Weight;
                Bookmark birthday = doc.Range.Bookmarks["birthday"];
                birthday.Text = model.Birthday.ToString("yyyy-MM-dd");
                Bookmark phone = doc.Range.Bookmarks["phone"];
                phone.Text = model.Phone;
                Bookmark email = doc.Range.Bookmarks["email"];
                email.Text = model.Email;
                Bookmark qqnumber = doc.Range.Bookmarks["qqnumber"];
                qqnumber.Text = model.Email;

                Bookmark address = doc.Range.Bookmarks["address"];
                address.Text = model.Address;
                Bookmark presentaddress = doc.Range.Bookmarks["presentaddress"];
                presentaddress.Text = model.PresentAddress;
                Bookmark imgpath = doc.Range.Bookmarks["imgpath"];
                imgpath.Text = model.ImgPath;
                Bookmark hobby = doc.Range.Bookmarks["hobby"];
                hobby.Text = model.Hobby;
                Bookmark goodat = doc.Range.Bookmarks["goodat"];
                goodat.Text = model.GoodAt;

                var path = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory + "/UserWord/"+model.Name+".doc");
                //重新生成一个word文档并保存
                doc.Save(path, SaveFormat.Doc);
                //定时删除下载的文档
                NeedHelp.time = new Timer(DeletWord, path, 50000, 300000);
                return path;

 这个没有试过,不过应该是可行的。不明白的话可看源文档

微软官方地址https://docs.microsoft.com/zh-cn/office/troubleshoot/office-developer/automate-word-create-file-using-visual-c

参考地址https://www.cnblogs.com/xiaoyaodijun/p/4642922.html 使用插件

https://www.cnblogs.com/tuqun/p/5083669.html#4162686

--------------------------------------

感谢下面大哥提供的另一种方式,不过我没尝试

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值