C# 处理Word自动生成报告 一、概述

C# 处理Word自动生成报告 二、数据源例子

C# 处理Word自动生成报告 三、设计模板

C# 处理Word自动生成报告 四、程序处理

现在说一下程序处理部分,有点长

本来是想做针对doc和docx的模板两个版本, 后来想到可以在生成的时候saveas里设置格式,

所以此版只支持对docx的模板处理,

想要doc的情况可以选择生成格式为doc的.

上代码:

 public class WordHelper
    {
        private Word.Application wordApp = null;
        private Word.Document wordDoc = null;
        private DataSet dataSource = null;
        private object line = Word.WdUnits.wdLine;
        private string errorMsg = "";

        /// <summary>
        /// 根据模板文件,创建数据报告
        /// </summary>
        /// <param name="templateFile">模板文件名(含路径)</param>
        /// <param name="newFilePath">新文件路径)</param>
        /// <param name="dataSource">数据源,包含多个datatable</param>
        /// <param name="saveFormat">新文件格式:</param>
        )
        {
            this.dataSource = dataSource;
            errorMsg = this.errorMsg;
            bool rtn = OpenTemplate(templateFile)
                && SetContent(].Rows[]))
                && UpdateTablesOfContents()
                && SaveFile(newFilePath, ref newFileName, saveFormat);

            CloseAndClear();
            return rtn;
        }
        private bool OpenTemplate(string templateFile)
        {
            if (!File.Exists(templateFile))
            {
                return false;
            }

            wordApp = new Word.ApplicationClass();
            wordApp.Visible = false;//使文档可见,调试用
            wordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
            object file = templateFile;
            wordDoc = wordApp.Documents.Open(ref file, ReadOnly: true);
            return true;
        }

        private bool SetContent(WordElement element)
        {
            string currBookMarkName = string.Empty;
            ).ToString() + "_";
            foreach (Word.Bookmark item in element.Range.Bookmarks)
            {
                currBookMarkName = item.Name;

                if (currBookMarkName.StartsWith(startWith) && (!currBookMarkName.Equals(element.ElementName)))
                {
                    SetLoop(new WordElement(item.Range, currBookMarkName, element.DataRow, element.GroupBy));
                }

            }

            SetLabel(element);

            SetTable(element);

            SetChart(element);

            return true;
        }
        private bool SetLoop(WordElement element)
        {
            DataRow[] dataRows = dataSource.Tables[element.TableIndex].Select(element.GroupByString);
            int count = dataRows.Count();
            element.Range.Select();

            //第0行作为模板  先从1开始  循环后处理0行;
            ; i < count; i++)
            {

                element.Range.Copy();  //模板loop复制
                wordApp.Selection.InsertParagraphAfter();//换行 不会清除选中的内容,TypeParagraph 等同于回车,若当前有选中内容会被清除. TypeParagraph 会跳到下一行,InsertParagraphAfter不会, 所以movedown一下.
                wordApp.Selection.MoveDown(ref line, Missing.Value, Missing.Value);
                wordApp.Selection.Paste(); //换行后粘贴复制内容
                int offset = wordApp.Selection.Range.End - element.Range.End; //计算偏移量

                //复制书签,书签名 = 模板书签名 + 复制次数
                foreach (Word.Bookmark subBook in element.Range.Bookmarks)
                {
                    if (subBook.Name.Equals(element.ElementName))
                    {
                        continue;
                    }

                    wordApp.Selection.Bookmarks.Add(subBook.Name + "_" + i.ToString(), wordDoc.Range(subBook.Start + offset, subBook.End + offset));
                }

                SetContent(new WordElement(wordDoc.Range(wordApp.Selection.Range.End - (element.Range.End - element.Range.Start), wordApp.Selection.Range.End), element.ElementName + "_" + i.ToString(), dataRows[i], element.GroupBy));
            }

            element.Range.Delete();

            return true;
        }
        private bool SetLabel(WordElement element)
        {
            )
            {
                string startWith = "label_" + element.Level.ToString() + "_";
                string bookMarkName = string.Empty;
                foreach (Word.Bookmark item in element.Range.Bookmarks)
                {
                    bookMarkName = item.Name;

                    if (bookMarkName.StartsWith(startWith))
                    {
                        bookMarkName = WordElement.GetName(bookMarkName);

                        item.Range.Text = element.DataRow[bookMarkName].ToString();
                    }
                }
            }

            return true;
        }
        private bool SetTable(WordElement element)
        {
            )
            {
                string startWith = "table_" + element.Level.ToString() + "_";
                foreach (Word.Table table in element.Range.Tables)
                {
                    if (!string.IsNullOrEmpty(table.Title) && table.Title.StartsWith(startWith))
                    {
                        WordElement tableElement = new WordElement(null, table.Title, element.DataRow);

                        TableConfig config = new TableConfig(table.Descr);

                        object dataRowTemplate = table.Rows[config.DataRow];
                        Word.Row SummaryRow = null;
                        DataRow SummaryDataRow = null;
                        DataTable dt = dataSource.Tables[tableElement.TableIndex];
                        DataRow[] dataRows = dataSource.Tables[tableElement.TableIndex].Select(tableElement.GroupByString); ;

                        )
                        {
                            SummaryRow = table.Rows[config.SummaryRow];
                            SummaryDataRow = dt.Select(string.IsNullOrEmpty(tableElement.GroupByString) ? config.SummaryFilter : tableElement.GroupByString + " and  " + config.SummaryFilter).FirstOrDefault();
                        }

                        foreach (DataRow row in dataRows)
                        {
                            if (row == SummaryDataRow)
                            {
                                continue;
                            }

                            Word.Row newRow = table.Rows.Add(ref dataRowTemplate);
                            ; j < table.Columns.Count; j++)
                            {
                                newRow.Cells[j + ].Range.Text = row[j].ToString(); ;
                            }

                        }

                        ((Word.Row)dataRowTemplate).Delete();

                         && SummaryDataRow != null)
                        {
                            ; j < SummaryRow.Cells.Count; j++)
                            {
                                ].Range.Text.Trim().Replace("\r\a", "");

                                 && dt.Columns.Contains(temp.Substring(, temp.Length - )))
                                {
                                    SummaryRow.Cells[j + ].Range.Text = SummaryDataRow[temp.Substring(, temp.Length - )].ToString();
                                }
                            }
                        }

                        table.Title = tableElement.Name;
                    }

                }
            }

            return true;
        }
        private bool SetChart(WordElement element)
        {
            )
            {
                List<Word.InlineShape> chartList = element.Range.InlineShapes.Cast<Word.InlineShape>().Where(m => m.Type == Word.WdInlineShapeType.wdInlineShapeChart).ToList();
                string startWith = "chart_" + element.Level.ToString() + "_";
                foreach (Word.InlineShape item in chartList)
                {
                    Word.Chart chart = item.Chart;
                    if (!string.IsNullOrEmpty(chart.ChartTitle.Text) && chart.ChartTitle.Text.StartsWith(startWith))
                    {
                        WordElement chartElement = new WordElement(null, chart.ChartTitle.Text, element.DataRow);

                        DataTable dataTable = dataSource.Tables[chartElement.TableIndex];
                        DataRow[] dataRows = dataTable.Select(chartElement.GroupByString);

                        int columnCount = dataTable.Columns.Count;
                        List<int> columns = new List<int>();

                        foreach (var dr in dataRows)
                        {
                             ?  : chartElement.ColumnStart - ; i < (chartElement.ColumnEnd == - ? columnCount : chartElement.ColumnEnd); i++)
                            {
                                if (columns.Contains(i) || dr[i] == null || string.IsNullOrEmpty(dr[i].ToString()))
                                {

                                }
                                else
                                {
                                    columns.Add(i);
                                }
                            }
                        }
                        columns.Sort();
                        columnCount = columns.Count;
                        int rowsCount = dataRows.Length;

                        Word.ChartData chartData = chart.ChartData;

                        //chartData.Activate();
                        //此处有个比较疑惑的问题, 不执行此条,生成的报告中的图表无法再次右键编辑数据. 执行后可以, 但有两个问题就是第一会弹出Excel框, 处理完后会自动关闭. 第二部分chart的数据range设置总不对
                        //不知道是不是版本的问题, 谁解决了分享一下,谢谢

                        Excel.Workbook dataWorkbook = (Excel.Workbook)chartData.Workbook;
                        dataWorkbook.Application.Visible = false;

                        Excel.Worksheet dataSheet = (Excel.Worksheet)dataWorkbook.Worksheets[];
                        //设定范围
                         : rowsCount) + "|" + columnCount;
                        Console.WriteLine(a);

                        Excel.Range tRange = dataSheet.Range[ : rowsCount), columnCount]];
                        Excel.ListObject tbl1 = dataSheet.ListObjects[];
                        //dataSheet.ListObjects[1].Delete(); //想过重新删除再添加  这样 原有数据清掉了, 但觉得性能应该会有所下降
                        //Excel.ListObject tbl1 = dataSheet.ListObjects.AddEx();
                        tbl1.Resize(tRange);
                        ; j < rowsCount; j++)
                        {
                            DataRow row = dataRows[j];
                            ; k < columnCount; k++)
                            {
                                dataSheet.Cells[j + , k + ].FormulaR1C1 = row[columns[k]];
                            }
                        }

                        if (chartElement.ColumnNameForHead)
                        {
                            ; k < columns.Count; k++)
                            {
                                dataSheet.Cells[, k + ].FormulaR1C1 = dataTable.Columns[columns[k]].ColumnName;
                            }
                        }
                        chart.ChartTitle.Text = chartElement.Name;
                        //dataSheet.Application.Quit();
                    }
                }
            }

            return true;
        }
        private bool UpdateTablesOfContents()
        {
            foreach (Word.TableOfContents item in wordDoc.TablesOfContents)
            {
                item.Update();
            }

            return true;
        }
        )
        {
            if (string.IsNullOrEmpty(newFileName))
            {
                newFileName = DateTime.Now.ToString("yyyyMMddHHmmss");

                switch (saveFormat)
                {
                    :// Word.WdSaveFormat.wdFormatDocument
                        newFileName += ".doc";
                        break;
                    :// Word.WdSaveFormat.wdFormatDocumentDefault
                        newFileName += ".docx";
                        break;
                    :// Word.WdSaveFormat.wdFormatPDF
                        newFileName += ".pdf";
                        break;
                    default:
                        break;
                }
            }

            object newfile = Path.Combine(newFilePath, newFileName);
            object wdSaveFormat = saveFormat;
            wordDoc.SaveAs(ref newfile, ref wdSaveFormat);
            return true;
        }

        private void CloseAndClear()
        {
            if (wordApp == null)
            {
                return;
            }
            wordDoc.Close(Word.WdSaveOptions.wdDoNotSaveChanges);
            wordApp.Quit(Word.WdSaveOptions.wdDoNotSaveChanges);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(wordDoc);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
            wordDoc = null;
            wordApp = null;
            GC.Collect();
            KillProcess("Excel","WINWORD");
        }

        private void KillProcess(params string[] processNames)
        {
            //Process myproc = new Process();
            //得到所有打开的进程
            try
            {
                foreach (string name in processNames)
                {
                    foreach (Process thisproc in Process.GetProcessesByName(name))
                    {
                        if (!thisproc.CloseMainWindow())
                        {
                            if (thisproc != null)
                                thisproc.Kill();
                        }
                    }
                }
            }
            catch (Exception)
            {
                //throw Exc;
                // msg.Text+=  "杀死"  +  processName  +  "失败!";
            }
        }
    }

    public class WordElement
    {
        )
        {
            this.Range = range;
            this.ElementName = elementName;
            this.GroupBy = groupBy;
            this.DataRow = dataRow;
            if (string.IsNullOrEmpty(elementName))
            {
                ;
                this.TableIndex = tableIndex;
                this.Name = string.Empty;
                this.ColumnNameForHead = false;
            }
            else
            {
                string[] element = elementName.Split('_');
                ]);
                this.ColumnNameForHead = false;
                ;
                ;

                ].Equals("label"))
                {
                    ];
                    ;
                }
                else
                {
                    ];
                    ]) - ;

                    ]))
                    {
                        ].Split(new string[] { "XX" }, StringSplitOptions.RemoveEmptyEntries);
                        if (this.GroupBy == null)
                        {
                            this.GroupBy = new Dictionary<string, string>();
                        }
                        foreach (string item in filters)
                        {
                            if (!this.GroupBy.Keys.Contains(item))
                            {
                                this.GroupBy.Add(item, dataRow[item].ToString());
                            }

                        }
                    }

                    ].Equals()
                    {
                        ].Equals(");
                        ]) ? - : ]);
                        ]) ? - : ]);
                    }
                }
            }
        }

        public Word.Range Range { get; set; }
        public int Level { get; set; }
        public int TableIndex { get; set; }
        public string ElementName { get; set; }

        public DataRow DataRow { get; set; }
        public Dictionary<string, string> GroupBy { get; set; }

        public string Name { get; set; }

        public bool ColumnNameForHead { get; set; }
        public int ColumnStart { get; set; }
        public int ColumnEnd { get; set; }

        public string GroupByString
        {
            get
            {
                )
                {
                    return string.Empty;
                }

                string rtn = string.Empty;
                foreach (string key in this.GroupBy.Keys)
                {
                    rtn += "and " + key + " = '" + GroupBy[key] + "' ";
                }
                );
            }
        }

        public static string GetName(string elementName)
        {
            string[] element = elementName.Split('_');

            ].Equals("label"))
            {
                ];
            }
            else
            {
                ];
            }
        }
    }

    public class TableConfig
    {
        public TableConfig(string tableDescr = "")
        {
            ;
            ;

            if (!string.IsNullOrEmpty(tableDescr))
            {
                string[] element = tableDescr.Split(',');
                foreach (string item in element)
                {
                    if (!string.IsNullOrEmpty(item))
                    {
                        string[] configs = item.Split(':');
                        )
                        {
                            ].ToLower())
                            {
                                case "data":
                                case "d":
                                    ]);
                                    break;
                                case "summary":
                                case "s":
                                    ]);
                                    break;
                                case "summaryfilter":
                                case "sf":
                                    ];
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            }

        }
        public int DataRow { get; set; }
        public int SummaryRow { get; set; }
        public string SummaryFilter { get; set; }
    }

后续问题: 1.部署: 目前我的开发环境里装的是office2016 的office365版 引用的是  Microsoft Word 16.0 Object Library, 对应的Microsoft.Office.Interop.Word.dll版本是15.0...

发现office2013版本也是15, 只是小版本不同, 没找到office 2016 和2013的 primary interop assembly, 莫非部署的环境里也要安装完整的office?

为了避免文件占用问题,打开模板采用了只读方式打开wordDoc = wordApp.Documents.Open(ref file, ReadOnly: true);  在office2016(office365)版测试通过, 但专业版测试失败.

ReadOnly: false的情况下, office2016  office2013均测试通过.

2. word中嵌入的Excel图表的问题, 虽然生成结果中的图表数据是正确的, 但无法右键再次编辑数据, 只可修改样式.

3. 性能问题: 处理速度较慢.

希望有知道的看到给个回复.  打算有时间研究一下OpenXML, 希望能完美解决上面的问题.

C# 处理Word自动生成报告 四、程序处理的更多相关文章

  1. C# 处理Word自动生成报告 三、设计模板

    C# 处理Word自动生成报告 一.概述 C# 处理Word自动生成报告 二.数据源例子 C# 处理Word自动生成报告 三.设计模板 C# 处理Word自动生成报告 四.程序处理 既然是模板就少不了 ...

  2. C# 处理Word自动生成报告 一、概述

    经常遇到这样的需求, 生成Word格式的报告, 而不是单纯的一张表格的报表.  就像体检报告一样. 数据来源部分决定采用一个存储过程返回Dataset的方式, 整张报告的数据来源于此Dataset的多 ...

  3. C# 处理Word自动生成报告 二、数据源例子

    还是以学生.语文.数学.分数为例吧, 感觉这个和helloworld都有一拼了. 造一张表如下, 整张报表就围绕这个表转圈了, 顺便说下就是名字如有雷同纯属巧合 新建个存储过程 ALTER PROCE ...

  4. Word自动生成目录

    博主最近在写报告的时候要在Word里面做个目录,再做个页码,然后上网搜了一些方法,非常零散,我弄了好久才弄好.在这里我把整套方法分享一下. 声明:内容完全独创! 工具:Word 2016. 效果:如下 ...

  5. jmeter自动生成报告

    从JMeter 3.0开始已支持自动生成动态报告,我们可以更容易根据生成的报告来完成我们的性能测试报告. 如何生成html测试报告 如果未生成结果文件(.jtl),可运行如下命令生成报告: jmete ...

  6. 利用html实现类似于word自动生成的目录的效果

    在word中的自动生成目录当中,我们会看到是这样的目录结构: 嗯,自动生成固然是简单,但是在html当中,却没有一个合适的标签来去做.今天后台导出PDF的时候告诉我,他需要用html做一个这样的结构, ...

  7. 自动生成百度小程序sitemap.txt文件路径

    因为业务需要,需要在目前项目上开发一个百度小程序,百度智能小程序上线了,但是内容每天得推送,不可能一个小程序路径一个推送吧,因为小程序路径和项目路径不一致. 因为项目是用ThinkPHP开发的,在此附 ...

  8. 使用LaTeX和KnitR自动生成报告

    扩展名为.Rnw(Rtex)的文件就是包含了R代码的LaTeX文档.编译的时候,先用Rscript调用Knitr处理,生成.TeX文档,然后用pdfLaTeX/XeLaTeX编译成PDF. 最方便的编 ...

  9. 写了个自动生成vcxproj的程序

    背景: 公司的vcxproj有个模板,必须要遵守 程序测试 config = { { ProjName = 'my_exe', ClCompile = {'main.cpp', 'main2.cpp' ...

随机推荐

  1. [Spark性能调优] 第三章 : Spark 2.1.0 中 Sort-Based Shuffle 产生的内幕

    本課主題 Sorted-Based Shuffle 的诞生和介绍 Shuffle 中六大令人费解的问题 Sorted-Based Shuffle 的排序和源码鉴赏 Shuffle 在运行时的内存管理 ...

  2. centos7下固定IP(静态IP)网络配置

    关于centos下网络配置(这里使用静态IP方法) 动态ip网络配置可参考我的另一篇博文http://www.cnblogs.com/albertrui/p/7811868.html 1.编辑/etc ...

  3. 一个InnoDB性能超过Oracle的调优Case

    年前抽空到兄弟公司支援了一下Oracle迁移MySQL的测试,本想把MySQL调优到接近Oracle的性能即可,但经过 @何_登成 @淘宝丁奇 @淘宝褚霸 @淘伯松 诸位大牛的指导和帮助(排名不分先后 ...

  4. .net 平台下, Socket通讯协议中间件设计思路(附源码)

    .net 平台下,实现通讯处理有很多方法(见下表),各有利弊: 序号 实现方式 特点 1 WCF 优点:封装好,方便.缺点:难学,不跨平台 2 RocketMQ,SuperSocket等中间件 优点: ...

  5. StackExchange.Redis学习笔记(五) 发布和订阅

    Redis命令中的Pub/Sub Redis在 2.0之后的版本中 实现了 事件推送的  发布订阅命令 以下是Redis关于发布和订阅提供的相关命令 SUBSCRIBE channel [channe ...

  6. C#要点补充

    1字符串与时间的互转 DateTime.TryParse将空字符串.为null或格式不正确,则转换为的DateTime所代表的值为:0001/1/1 0:00:00,此为DateTime.MinVal ...

  7. Django----->一周后的重温

    Django   一 什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来 ...

  8. 读书笔记《CSS权威指南》

    阅读本书主要目的: 自从学会CSS以来,虽然熟练掌握了其使用方法和技巧,但对其底层的原理和实现并不清晰,阅读本书想进一步系统化的学习和深入研究其本质,对这门前端基础语言从熟练使用到真正理解. 第1章 ...

  9. IO(文件)处理

    一.文件操作 1)介绍: 计算机系统分为:计算机硬件,操作系统,应用程序三部分. 我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到应用程序要操作硬件, ...

  10. sublime 设置新建文件自动添加author(作者)等文件头信息

    很多时候, sublime 自带自动添加文件头信息, 但是并不是我们想要比如下面这样的:新建一个python文件 自动添加的author 信息== 上面并不是我想要的, 我想要下面这样的效果:== 这 ...