├── demo
├── TemplateDemo
│ └── WordTemplate.docx
└── ProcedureDemo
│ └── DataBaseToWord_Proc.sql
├── src
└── FlyLolo.WordReport.Demo
│ ├── FlyLolo.WordReport.Demo
│ ├── Properties
│ │ ├── Settings.settings
│ │ ├── AssemblyInfo.cs
│ │ ├── Settings.Designer.cs
│ │ ├── Resources.Designer.cs
│ │ └── Resources.resx
│ ├── App.config
│ ├── Program.cs
│ ├── Form1.cs
│ ├── SqlHelper.cs
│ ├── Form1.Designer.cs
│ ├── FlyLolo.WordReport.Demo.csproj
│ ├── Form1.resx
│ └── WordReportHelper.cs
│ └── FlyLolo.WordReport.Demo.sln
├── README.md
├── .gitignore
└── LICENSE
/demo/TemplateDemo/WordTemplate.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlyLolo/WordReport/HEAD/demo/TemplateDemo/WordTemplate.docx
--------------------------------------------------------------------------------
/demo/ProcedureDemo/DataBaseToWord_Proc.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlyLolo/WordReport/HEAD/demo/ProcedureDemo/DataBaseToWord_Proc.sql
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WordReport
2 | 经常会有生成word版本的报告的例子, 例如体检报告;
3 | 这是一个通用的Word报告生成程序, 将Dataset中的数据按照设定的规则写入模板,支持导出docx、doc和PDF.
4 | Dataset指提供数据, 报告中的样式(例如字体、表格宽度、对齐方式等)全部在word模板中可视化定制.
5 |
6 | 功能已经实现, 一些细节暂未处理, 比如对于模板配置错误时的友好提示和日志.
7 | 速度有点慢, 据说OpenXML会好很多,但据说只支持word的docx版本,导出doc和pdf不知道是否可行, 有时间深入研究一下.
8 |
9 |
10 | # Demo
11 | 做了个将Sql Server数据库的表结构导出的demo.
12 |
13 | # 使用方法
14 | 1.将文档需要的数据整理到一个Dataset(本文以sql server做的例子, 您可以使用其他的).
15 | 2.新建一个docx格式的word文档, 通过新建书签的方式划定区域,规则见下文.
16 | 3.根据书签中的描述, 系统自动将数据写入相应位置.
17 |
18 | # 模板规则
19 | 见我的博客https://www.cnblogs.com/FlyLolo/p/WordReport.html. 当时写的有点粗糙, 有时间整理一下
20 |
21 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace FlyLolo.WordReport.Demo
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// 应用程序的主入口点。
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault(false);
19 | Application.Run(new Form1());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("FlyLolo.WordReport.Demo")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("FlyLolo.WordReport.Demo")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("dcf96f54-6ba8-4d88-958c-1c7452a7d2a2")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace FlyLolo.WordReport.Demo.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27130.2036
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlyLolo.WordReport.Demo", "FlyLolo.WordReport.Demo\FlyLolo.WordReport.Demo.csproj", "{DCF96F54-6BA8-4D88-958C-1C7452A7D2A2}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {DCF96F54-6BA8-4D88-958C-1C7452A7D2A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {DCF96F54-6BA8-4D88-958C-1C7452A7D2A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {DCF96F54-6BA8-4D88-958C-1C7452A7D2A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {DCF96F54-6BA8-4D88-958C-1C7452A7D2A2}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {9D2626C9-2DF3-4C9F-9BC9-B145096893CF}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/Form1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 | using FlyLolo.WordReport;
11 |
12 | namespace FlyLolo.WordReport.Demo
13 | {
14 | public partial class Form1 : Form
15 | {
16 | public Form1()
17 | {
18 | InitializeComponent();
19 | init();
20 | }
21 |
22 | private void btnCreate_Click(object sender, EventArgs e)
23 | {
24 | DataSet dataSource = SqlHelper.ExecuteDataSet("DefaultConn", "DataBaseToWord");
25 | create(dataSource);
26 | }
27 |
28 | private void create(DataSet ds)
29 | {
30 | WordReportHelper helper = new WordReportHelper();
31 | int a = cbxType.SelectedIndex;
32 | string newFileName = "";
33 | string errorMsg = "";
34 | helper.CreateReport(@"d:\WordTemplate.docx", ds, out errorMsg, @"d:\", ref newFileName, int.Parse(cbxType.SelectedValue.ToString()));
35 | }
36 |
37 | private void init()
38 | {
39 | DataTable dt = new DataTable();
40 | DataColumn dc1 = new DataColumn("id");
41 | DataColumn dc2 = new DataColumn("name");
42 | dt.Columns.Add(dc1);
43 | dt.Columns.Add(dc2);
44 |
45 | DataRow dr1 = dt.NewRow();
46 | dr1["id"] = 16;
47 | dr1["name"] = "Word2007";
48 |
49 | DataRow dr2 = dt.NewRow();
50 | dr2["id"] = 0;
51 | dr2["name"] = "Word97-2003";
52 |
53 | DataRow dr3 = dt.NewRow();
54 | dr3["id"] = 17;
55 | dr3["name"] = "PDF";
56 |
57 | dt.Rows.Add(dr1);
58 | dt.Rows.Add(dr2);
59 | dt.Rows.Add(dr3);
60 |
61 | cbxType.DataSource = dt;
62 | cbxType.ValueMember = "id";
63 | cbxType.DisplayMember = "name";
64 | }
65 |
66 | private void Form1_Load(object sender, EventArgs e)
67 | {
68 |
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/SqlHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Data.SqlClient;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace FlyLolo.WordReport.Demo
10 | {
11 | public static class SqlHelper
12 | {
13 | public static string GetConnectionString(string connName)
14 | {
15 | return System.Configuration.ConfigurationManager.ConnectionStrings[connName].ToString();
16 | }
17 | public static DataSet ExecuteDataSet(string connName, string procName, params IDataParameter[] procParams)
18 | {
19 | SqlConnection conn = null;
20 | DataSet ds = new DataSet();
21 | SqlDataAdapter da = new SqlDataAdapter();
22 | SqlCommand cmd = null;
23 |
24 | try
25 | {
26 | //Setup command object
27 | cmd = new SqlCommand(procName);
28 | cmd.CommandType = CommandType.Text;
29 | if (procParams != null)
30 | {
31 | for (int index = 0; index < procParams.Length; index++)
32 | {
33 | if (procParams[index] != null)
34 | {
35 | cmd.Parameters.Add(procParams[index]);
36 | }
37 | else
38 | {
39 | break;
40 | }
41 |
42 | }
43 | }
44 | da.SelectCommand = (SqlCommand)cmd;
45 | string connstr = GetConnectionString(connName);
46 | conn = new SqlConnection(connstr);
47 | cmd.Connection = conn;
48 | conn.Open();
49 |
50 | //Fill the dataset
51 | da.Fill(ds);
52 | }
53 | catch
54 | {
55 | throw;
56 | }
57 | finally
58 | {
59 | if (da != null) da.Dispose();
60 | if (cmd != null) cmd.Dispose();
61 | conn.Dispose(); //Implicitly calls cnx.Close()
62 | }
63 | return ds;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/Form1.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace FlyLolo.WordReport.Demo
2 | {
3 | partial class Form1
4 | {
5 | ///
6 | /// 必需的设计器变量。
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// 清理所有正在使用的资源。
12 | ///
13 | /// 如果应释放托管资源,为 true;否则为 false。
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows 窗体设计器生成的代码
24 |
25 | ///
26 | /// 设计器支持所需的方法 - 不要修改
27 | /// 使用代码编辑器修改此方法的内容。
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.cbxType = new System.Windows.Forms.ComboBox();
32 | this.btnCreate = new System.Windows.Forms.Button();
33 | this.SuspendLayout();
34 | //
35 | // cbxType
36 | //
37 | this.cbxType.FormattingEnabled = true;
38 | this.cbxType.Location = new System.Drawing.Point(64, 119);
39 | this.cbxType.Name = "cbxType";
40 | this.cbxType.Size = new System.Drawing.Size(75, 20);
41 | this.cbxType.TabIndex = 3;
42 | //
43 | // btnCreate
44 | //
45 | this.btnCreate.Location = new System.Drawing.Point(145, 119);
46 | this.btnCreate.Name = "btnCreate";
47 | this.btnCreate.Size = new System.Drawing.Size(75, 23);
48 | this.btnCreate.TabIndex = 2;
49 | this.btnCreate.Text = "create";
50 | this.btnCreate.UseVisualStyleBackColor = true;
51 | this.btnCreate.Click += new System.EventHandler(this.btnCreate_Click);
52 | //
53 | // Form1
54 | //
55 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
56 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
57 | this.ClientSize = new System.Drawing.Size(284, 261);
58 | this.Controls.Add(this.cbxType);
59 | this.Controls.Add(this.btnCreate);
60 | this.Name = "Form1";
61 | this.Text = "Form1";
62 | this.Load += new System.EventHandler(this.Form1_Load);
63 | this.ResumeLayout(false);
64 |
65 | }
66 |
67 | #endregion
68 |
69 | private System.Windows.Forms.ComboBox cbxType;
70 | private System.Windows.Forms.Button btnCreate;
71 | }
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace FlyLolo.WordReport.Demo.Properties
12 | {
13 |
14 |
15 | ///
16 | /// 强类型资源类,用于查找本地化字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// 返回此类使用的缓存 ResourceManager 实例。
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FlyLolo.WordReport.Demo.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// 覆盖当前线程的 CurrentUICulture 属性
56 | /// 使用此强类型的资源类的资源查找。
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DCF96F54-6BA8-4D88-958C-1C7452A7D2A2}
8 | WinExe
9 | FlyLolo.WordReport.Demo
10 | FlyLolo.WordReport.Demo
11 | v4.5
12 | 512
13 |
14 |
15 | AnyCPU
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | AnyCPU
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | Form
50 |
51 |
52 | Form1.cs
53 |
54 |
55 |
56 |
57 |
58 |
59 | Form1.cs
60 |
61 |
62 | ResXFileCodeGenerator
63 | Resources.Designer.cs
64 | Designer
65 |
66 |
67 | True
68 | Resources.resx
69 |
70 |
71 | SettingsSingleFileGenerator
72 | Settings.Designer.cs
73 |
74 |
75 | True
76 | Settings.settings
77 | True
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | {2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}
86 | 2
87 | 8
88 | 0
89 | primary
90 | False
91 | True
92 |
93 |
94 | {00020813-0000-0000-C000-000000000046}
95 | 1
96 | 9
97 | 0
98 | primary
99 | False
100 | True
101 |
102 |
103 | {00020905-0000-0000-C000-000000000046}
104 | 8
105 | 7
106 | 0
107 | primary
108 | False
109 | True
110 |
111 |
112 | {0002E157-0000-0000-C000-000000000046}
113 | 5
114 | 3
115 | 0
116 | primary
117 | False
118 | True
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/Form1.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/src/FlyLolo.WordReport.Demo/FlyLolo.WordReport.Demo/WordReportHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Reflection;
8 | using Excel = Microsoft.Office.Interop.Excel;
9 | using Word = Microsoft.Office.Interop.Word;
10 |
11 | namespace FlyLolo.WordReport.Demo
12 | {
13 | public class WordReportHelper
14 | {
15 | private Word.Application wordApp = null;
16 | private Word.Document wordDoc = null;
17 | private DataSet dataSource = null;
18 | private object line = Word.WdUnits.wdLine;
19 | private string errorMsg = "";
20 |
21 | ///
22 | /// 根据模板文件,创建数据报告
23 | ///
24 | /// 模板文件名(含路径)
25 | /// 新文件路径)
26 | /// 数据源,包含多个datatable
27 | /// 新文件格式:
28 | public bool CreateReport(string templateFile, DataSet dataSource, out string errorMsg, string newFilePath, ref string newFileName, int saveFormat = 16)
29 | {
30 | this.dataSource = dataSource;
31 | errorMsg = this.errorMsg;
32 | bool rtn = OpenTemplate(templateFile)
33 | && SetContent(new WordElement(wordDoc.Range(), dataRow: dataSource.Tables[dataSource.Tables.Count - 1].Rows[0]))
34 | && UpdateTablesOfContents()
35 | && SaveFile(newFilePath, ref newFileName, saveFormat);
36 |
37 | CloseAndClear();
38 | return rtn;
39 | }
40 |
41 | ///
42 | /// 打开模板文件
43 | ///
44 | ///
45 | ///
46 | private bool OpenTemplate(string templateFile)
47 | {
48 | if (!File.Exists(templateFile))
49 | {
50 | return false;
51 | }
52 |
53 | wordApp = new Word.Application();
54 | wordApp.Visible = true;//使文档可见,调试用
55 | wordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
56 | object file = templateFile;
57 | wordDoc = wordApp.Documents.Open(ref file, ReadOnly: false);
58 | return true;
59 | }
60 |
61 | ///
62 | /// 为指定区域写入数据
63 | ///
64 | ///
65 | ///
66 | private bool SetContent(WordElement element)
67 | {
68 | string currBookMarkName = string.Empty;
69 | string startWith = "loop_" + (element.Level + 1).ToString() + "_";
70 | foreach (Word.Bookmark item in element.Range.Bookmarks)
71 | {
72 | currBookMarkName = item.Name;
73 |
74 | if (currBookMarkName.StartsWith(startWith) && (!currBookMarkName.Equals(element.ElementName)))
75 | {
76 | SetLoop(new WordElement(item.Range, currBookMarkName, element.DataRow, element.GroupBy));
77 | }
78 |
79 | }
80 |
81 | SetLabel(element);
82 |
83 | SetTable(element);
84 |
85 | SetChart(element);
86 |
87 | return true;
88 | }
89 |
90 | ///
91 | /// 处理循环
92 | ///
93 | ///
94 | ///
95 | private bool SetLoop(WordElement element)
96 | {
97 | DataRow[] dataRows = dataSource.Tables[element.TableIndex].Select(element.GroupByString);
98 | int count = dataRows.Count();
99 | element.Range.Select();
100 |
101 | //第0行作为模板 先从1开始 循环后处理0行;
102 | for (int i = 0; i < count; i++)
103 | {
104 |
105 | element.Range.Copy(); //模板loop复制
106 | wordApp.Selection.InsertParagraphAfter();//换行 不会清除选中的内容,TypeParagraph 等同于回车,若当前有选中内容会被清除. TypeParagraph 会跳到下一行,InsertParagraphAfter不会, 所以movedown一下.
107 | wordApp.Selection.MoveDown(ref line, Missing.Value, Missing.Value);
108 | wordApp.Selection.Paste(); //换行后粘贴复制内容
109 | int offset = wordApp.Selection.Range.End - element.Range.End; //计算偏移量
110 |
111 | //复制书签,书签名 = 模板书签名 + 复制次数
112 | foreach (Word.Bookmark subBook in element.Range.Bookmarks)
113 | {
114 | if (subBook.Name.Equals(element.ElementName))
115 | {
116 | continue;
117 | }
118 |
119 | wordApp.Selection.Bookmarks.Add(subBook.Name + "_" + i.ToString(), wordDoc.Range(subBook.Start + offset, subBook.End + offset));
120 | }
121 |
122 | 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));
123 | }
124 |
125 | element.Range.Delete();
126 |
127 | return true;
128 | }
129 |
130 | ///
131 | /// 处理简单Label
132 | ///
133 | ///
134 | ///
135 | private bool SetLabel(WordElement element)
136 | {
137 | if (element.Range.Bookmarks != null && element.Range.Bookmarks.Count > 0)
138 | {
139 | string startWith = "label_" + element.Level.ToString() + "_";
140 | string bookMarkName = string.Empty;
141 | foreach (Word.Bookmark item in element.Range.Bookmarks)
142 | {
143 | bookMarkName = item.Name;
144 |
145 | if (bookMarkName.StartsWith(startWith))
146 | {
147 | bookMarkName = WordElement.GetName(bookMarkName);
148 |
149 | item.Range.Text = element.DataRow[bookMarkName].ToString();
150 | }
151 | }
152 | }
153 |
154 | return true;
155 | }
156 |
157 | ///
158 | /// 填充Table
159 | ///
160 | ///
161 | ///
162 | private bool SetTable(WordElement element)
163 | {
164 | if (element.Range.Tables != null && element.Range.Tables.Count > 0)
165 | {
166 | string startWith = "table_" + element.Level.ToString() + "_";
167 | foreach (Word.Table table in element.Range.Tables)
168 | {
169 | if (!string.IsNullOrEmpty(table.Title) && table.Title.StartsWith(startWith))
170 | {
171 | WordElement tableElement = new WordElement(null, table.Title, element.DataRow);
172 |
173 | TableConfig config = new TableConfig(table.Descr);
174 |
175 | object dataRowTemplate = table.Rows[config.DataRow];
176 | Word.Row SummaryRow = null;
177 | DataRow SummaryDataRow = null;
178 | DataTable dt = dataSource.Tables[tableElement.TableIndex];
179 | DataRow[] dataRows = dataSource.Tables[tableElement.TableIndex].Select(tableElement.GroupByString); ;
180 |
181 | if (config.SummaryRow > 0)
182 | {
183 | SummaryRow = table.Rows[config.SummaryRow];
184 | SummaryDataRow = dt.Select(string.IsNullOrEmpty(tableElement.GroupByString) ? config.SummaryFilter : tableElement.GroupByString + " and " + config.SummaryFilter).FirstOrDefault();
185 | }
186 |
187 | foreach (DataRow row in dataRows)
188 | {
189 | if (row == SummaryDataRow)
190 | {
191 | continue;
192 | }
193 |
194 | Word.Row newRow = table.Rows.Add(ref dataRowTemplate);
195 | for (int j = 0; j < table.Columns.Count; j++)
196 | {
197 | newRow.Cells[j + 1].Range.Text = row[j].ToString(); ;
198 | }
199 |
200 | }
201 |
202 | ((Word.Row)dataRowTemplate).Delete();
203 |
204 | if (config.SummaryRow > 0 && SummaryDataRow != null)
205 | {
206 | for (int j = 0; j < SummaryRow.Cells.Count; j++)
207 | {
208 | string temp = SummaryRow.Cells[j + 1].Range.Text.Trim().Replace("\r\a", "");
209 |
210 | if (!string.IsNullOrEmpty(temp) && temp.Length > 2 && dt.Columns.Contains(temp.Substring(1, temp.Length - 2)))
211 | {
212 | SummaryRow.Cells[j + 1].Range.Text = SummaryDataRow[temp.Substring(1, temp.Length - 2)].ToString();
213 | }
214 | }
215 | }
216 |
217 | table.Title = tableElement.Name;
218 | }
219 |
220 |
221 | }
222 | }
223 |
224 | return true;
225 | }
226 |
227 | ///
228 | /// 处理图表
229 | ///
230 | ///
231 | ///
232 | private bool SetChart(WordElement element)
233 | {
234 | if (element.Range.InlineShapes != null && element.Range.InlineShapes.Count > 0)
235 | {
236 | List chartList = element.Range.InlineShapes.Cast().Where(m => m.Type == Word.WdInlineShapeType.wdInlineShapeChart).ToList();
237 | string startWith = "chart_" + element.Level.ToString() + "_";
238 | foreach (Word.InlineShape item in chartList)
239 | {
240 | Word.Chart chart = item.Chart;
241 | if (!string.IsNullOrEmpty(chart.ChartTitle.Text) && chart.ChartTitle.Text.StartsWith(startWith))
242 | {
243 | WordElement chartElement = new WordElement(null, chart.ChartTitle.Text, element.DataRow);
244 |
245 | DataTable dataTable = dataSource.Tables[chartElement.TableIndex];
246 | DataRow[] dataRows = dataTable.Select(chartElement.GroupByString);
247 |
248 | int columnCount = dataTable.Columns.Count;
249 | List columns = new List();
250 |
251 | foreach (var dr in dataRows)
252 | {
253 | for (int i = chartElement.ColumnStart == -1 ? 0 : chartElement.ColumnStart - 1; i < (chartElement.ColumnEnd == -1 ? columnCount : chartElement.ColumnEnd); i++)
254 | {
255 | if (columns.Contains(i) || dr[i] == null || string.IsNullOrEmpty(dr[i].ToString()))
256 | {
257 |
258 | }
259 | else
260 | {
261 | columns.Add(i);
262 | }
263 | }
264 | }
265 | columns.Sort();
266 | columnCount = columns.Count;
267 | int rowsCount = dataRows.Length;
268 |
269 | Word.ChartData chartData = chart.ChartData;
270 |
271 | //chartData.Activate();
272 | //此处有个比较疑惑的问题, 不执行此条,生成的报告中的图表无法再次右键编辑数据. 执行后可以, 但有两个问题就是第一会弹出Excel框, 处理完后会自动关闭. 第二部分chart的数据range设置总不对
273 | //不知道是不是版本的问题, 谁解决了分享一下,谢谢
274 |
275 | Excel.Workbook dataWorkbook = (Excel.Workbook)chartData.Workbook;
276 | dataWorkbook.Application.Visible = false;
277 |
278 | Excel.Worksheet dataSheet = (Excel.Worksheet)dataWorkbook.Worksheets[1];
279 | //设定范围
280 | string a = (chartElement.ColumnNameForHead ? rowsCount + 1 : rowsCount) + "|" + columnCount;
281 | Console.WriteLine(a);
282 |
283 | Excel.Range tRange = dataSheet.Range["A1", dataSheet.Cells[(chartElement.ColumnNameForHead ? rowsCount + 1 : rowsCount), columnCount]];
284 | Excel.ListObject tbl1 = dataSheet.ListObjects[1];
285 | //dataSheet.ListObjects[1].Delete(); //想过重新删除再添加 这样 原有数据清掉了, 但觉得性能应该会有所下降
286 | //Excel.ListObject tbl1 = dataSheet.ListObjects.AddEx();
287 | tbl1.Resize(tRange);
288 | for (int j = 0; j < rowsCount; j++)
289 | {
290 | DataRow row = dataRows[j];
291 | for (int k = 0; k < columnCount; k++)
292 | {
293 | dataSheet.Cells[j + 2, k + 1].FormulaR1C1 = row[columns[k]];
294 | }
295 | }
296 |
297 | if (chartElement.ColumnNameForHead)
298 | {
299 | for (int k = 0; k < columns.Count; k++)
300 | {
301 | dataSheet.Cells[1, k + 1].FormulaR1C1 = dataTable.Columns[columns[k]].ColumnName;
302 | }
303 | }
304 | chart.ChartTitle.Text = chartElement.Name;
305 | //dataSheet.Application.Quit();
306 | }
307 | }
308 | }
309 |
310 | return true;
311 | }
312 |
313 | ///
314 | /// 更新目录
315 | ///
316 | ///
317 | private bool UpdateTablesOfContents()
318 | {
319 | foreach (Word.TableOfContents item in wordDoc.TablesOfContents)
320 | {
321 | item.Update();
322 | }
323 |
324 | return true;
325 | }
326 |
327 | ///
328 | /// 保存文件
329 | ///
330 | ///
331 | ///
332 | ///
333 | ///
334 | private bool SaveFile(string newFilePath, ref string newFileName, int saveFormat = 16)
335 | {
336 | if (string.IsNullOrEmpty(newFileName))
337 | {
338 | newFileName = DateTime.Now.ToString("yyyyMMddHHmmss");
339 |
340 | switch (saveFormat)
341 | {
342 | case 0:// Word.WdSaveFormat.wdFormatDocument
343 | newFileName += ".doc";
344 | break;
345 | case 16:// Word.WdSaveFormat.wdFormatDocumentDefault
346 | newFileName += ".docx";
347 | break;
348 | case 17:// Word.WdSaveFormat.wdFormatPDF
349 | newFileName += ".pdf";
350 | break;
351 | default:
352 | break;
353 | }
354 | }
355 |
356 | object newfile = Path.Combine(newFilePath, newFileName);
357 | object wdSaveFormat = saveFormat;
358 | wordDoc.SaveAs(ref newfile, ref wdSaveFormat);
359 | return true;
360 | }
361 |
362 | ///
363 | /// 清理
364 | ///
365 | private void CloseAndClear()
366 | {
367 | if (wordApp == null)
368 | {
369 | return;
370 | }
371 | wordDoc.Close(Word.WdSaveOptions.wdDoNotSaveChanges);
372 | wordApp.Quit(Word.WdSaveOptions.wdDoNotSaveChanges);
373 | System.Runtime.InteropServices.Marshal.ReleaseComObject(wordDoc);
374 | System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
375 | wordDoc = null;
376 | wordApp = null;
377 | GC.Collect();
378 | KillProcess("Excel", "WINWORD");
379 | }
380 |
381 | ///
382 | /// 杀进程..
383 | ///
384 | ///
385 | private void KillProcess(params string[] processNames)
386 | {
387 | //Process myproc = new Process();
388 | //得到所有打开的进程
389 | try
390 | {
391 | foreach (string name in processNames)
392 | {
393 | foreach (Process thisproc in Process.GetProcessesByName(name))
394 | {
395 | if (!thisproc.CloseMainWindow())
396 | {
397 | if (thisproc != null)
398 | thisproc.Kill();
399 | }
400 | }
401 | }
402 | }
403 | catch (Exception)
404 | {
405 | //throw Exc;
406 | // msg.Text+= "杀死" + processName + "失败!";
407 | }
408 | }
409 | }
410 |
411 | ///
412 | /// 封装的Word元素
413 | ///
414 | public class WordElement
415 | {
416 | public WordElement(Word.Range range, string elementName = "", DataRow dataRow = null, Dictionary groupBy = null, int tableIndex = 0)
417 | {
418 | this.Range = range;
419 | this.ElementName = elementName;
420 | this.GroupBy = groupBy;
421 | this.DataRow = dataRow;
422 | if (string.IsNullOrEmpty(elementName))
423 | {
424 | this.Level = 0;
425 | this.TableIndex = tableIndex;
426 | this.Name = string.Empty;
427 | this.ColumnNameForHead = false;
428 | }
429 | else
430 | {
431 | string[] element = elementName.Split('_');
432 | this.Level = int.Parse(element[1]);
433 | this.ColumnNameForHead = false;
434 | this.ColumnStart = -1;
435 | this.ColumnEnd = -1;
436 |
437 | if (element[0].Equals("label"))
438 | {
439 | this.Name = element[2];
440 | this.TableIndex = 0;
441 | }
442 | else
443 | {
444 | this.Name = element[4];
445 | this.TableIndex = int.Parse(element[2]) - 1;
446 |
447 | if (!string.IsNullOrEmpty(element[3]))
448 | {
449 | string[] filters = element[3].Split(new string[] { "XX" }, StringSplitOptions.RemoveEmptyEntries);
450 | if (this.GroupBy == null)
451 | {
452 | this.GroupBy = new Dictionary();
453 | }
454 | foreach (string item in filters)
455 | {
456 | if (!this.GroupBy.Keys.Contains(item))
457 | {
458 | this.GroupBy.Add(item, dataRow[item].ToString());
459 | }
460 |
461 | }
462 | }
463 |
464 | if (element[0].Equals("chart") && element.Count() > 5)
465 | {
466 | this.ColumnNameForHead = element[5].Equals("1");
467 | this.ColumnStart = string.IsNullOrEmpty(element[6]) ? -1 : int.Parse(element[6]);
468 | this.ColumnEnd = string.IsNullOrEmpty(element[7]) ? -1 : int.Parse(element[7]);
469 | }
470 | }
471 | }
472 | }
473 |
474 | public Word.Range Range { get; set; }
475 | public int Level { get; set; }
476 | public int TableIndex { get; set; }
477 | public string ElementName { get; set; }
478 |
479 | public DataRow DataRow { get; set; }
480 | public Dictionary GroupBy { get; set; }
481 |
482 | public string Name { get; set; }
483 |
484 | public bool ColumnNameForHead { get; set; }
485 | public int ColumnStart { get; set; }
486 | public int ColumnEnd { get; set; }
487 |
488 | public string GroupByString
489 | {
490 | get
491 | {
492 | if (GroupBy == null || GroupBy.Count == 0)
493 | {
494 | return string.Empty;
495 | }
496 |
497 | string rtn = string.Empty;
498 | foreach (string key in this.GroupBy.Keys)
499 | {
500 | rtn += "and " + key + " = '" + GroupBy[key] + "' ";
501 | }
502 | return rtn.Substring(3);
503 | }
504 | }
505 |
506 | public static string GetName(string elementName)
507 | {
508 | string[] element = elementName.Split('_');
509 |
510 |
511 | if (element[0].Equals("label"))
512 | {
513 | return element[2];
514 | }
515 | else
516 | {
517 | return element[4];
518 | }
519 | }
520 | }
521 |
522 | ///
523 | /// Table配置项
524 | ///
525 | public class TableConfig
526 | {
527 | public TableConfig(string tableDescr = "")
528 | {
529 | this.DataRow = 2;
530 | this.SummaryRow = -1;
531 |
532 | if (!string.IsNullOrEmpty(tableDescr))
533 | {
534 | string[] element = tableDescr.Split(',');
535 | foreach (string item in element)
536 | {
537 | if (!string.IsNullOrEmpty(item))
538 | {
539 | string[] configs = item.Split(':');
540 | if (configs.Length == 2)
541 | {
542 | switch (configs[0].ToLower())
543 | {
544 | case "data":
545 | case "d":
546 | this.DataRow = int.Parse(configs[1]);
547 | break;
548 | case "summary":
549 | case "s":
550 | this.SummaryRow = int.Parse(configs[1]);
551 | break;
552 | case "summaryfilter":
553 | case "sf":
554 | this.SummaryFilter = configs[1];
555 | break;
556 | default:
557 | break;
558 | }
559 | }
560 | }
561 | }
562 | }
563 |
564 | }
565 | public int DataRow { get; set; }
566 | public int SummaryRow { get; set; }
567 | public string SummaryFilter { get; set; }
568 | }
569 | }
570 |
--------------------------------------------------------------------------------