经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
Word报告自动生成(例如 导出数据库结构)
来源:cnblogs  作者:FlyLolo  时间:2018/11/16 10:31:02  对本文有异议

        将很早之前写的一个小组件重新整理优化一下,做成一个通用的功能。适用于导出数据库的结构(表、字段等)到Word或将体检数据自动生成Word版的体检报告等。代码:Github

一、主要需要完成功能:

1. 灵活的配置规则及word样式设置(文本、表格、图表、颜色等).

2. 支持表格.

3. 支持图表.

4. 支持章节内容循环生成.

5. 支持目录.

6.支持文档结构图

7.更新指定位置的文字

8.支持pdf导出.

 

最后结果如下:

                                                                            图一

                                    图二

                                         图三

二、需求分析与实现方式

   功能主要涉及3个比较重要的部分:数据源、Word样式、配置规则。 

     为了简单,数据源决定采用一个存储过程返回Dataset的方式, 整张报告的数据来源于此Dataset的多个Datatable.

  样式与配置:首先想到的是写一个config文件,所有配置都放到一个文件里,然后将数据按照这个规则生成word。但无疑这样的配置项太多了,关键是“样式”问题,比如字体、颜色、表格宽度.....想想就头大。而且没有“所见即所得”的效果,配置完都不知道啥样。

后来决定采取修改的方式, 先以一个word文件作为模板,在模板中定义好上面提到的“样式”,然后在模板中做一个个标记,然后将数据按照规则更新到对应的标记。

                                                       图四

    而这个标记我们用到了word的一个叫【书签】的功能,打开word按ctrl+shift+F5, 打开书签功能,如下图:

                                 图五

这样将【规则】通过一系列规则的【书签】定义到word模板中。

三、规则配置

  思路确定了,那就开始设计如何通过【书签】将规则定义到word模板中去,这里决定将所有规则都通过【书签】实现,而放弃config文件的方式,这个更统一而且直观一些。

A.循环

      以图四为例,数据库有多少张表是不固定的,我们在制作模板的时候不可能先画好N(N为表的总数)个表格等待数据填充, 这里就会需要遍历数据源中提供的所有表结构数据,然后逐一形成表格。这里就需要将图四中的表格循环一下,自动复制生成多个这样的表格。当然,这只是一种情况,还有可能会出现循环嵌套循环的情况,那么我将这个循环定义成一个书签的时候按照这样的格式:

      loop_级别_表序号_filter_名称

含义如下:

     loop:代表这是一个循环。

     级别:默认文档级别为0,出现的第一层循环为1,其内部若再次嵌套循环则级别为2,依次类推。

     表序号:取Dataset中的第几张表(从1开始)

     filter:循环的时候可能会用到对datatable的查找过滤,在此写出,多个字段用XX隔开(因为此处不允许有下划线外其他特殊字符, 就用这个XX吧 )

     名称:loop名称,方便与其他 loop区别

 B.更新指定位置的文字

    如图四中的【服务器名】、【表总数】等,只需要替换对应的文字即可:

    label_级别_名称

含义如下:

     label:代表这是一个label。

     级别:默认文档级别为0,出现的第一层循环为1,其内部若再次嵌套循环则级别为2,依次类推。

     名称:label名称

     注意这里省略了表序号,当级别为0的时候 ,自动取最后一个datatable中的数据,因为这个label经常会用到其他表汇总的数据,可能会用到之前几张表的数据,所以放在其他表都处理好后。当级别为1的时候,自然取该级别循环的行数据。

C.表格

     表格的配置原本也想对表格添加书签,后来发现有个表格属性, 觉得写在这里更好一些。

 如上图所示,【标题】格式为:table_级别_取Dataset中的第几张表(从1开始)_filter字段多个用XX隔开(此处不允许有下划线外其他特殊字符, 就用这个XX吧 )_名称

【说明】为可选项,若需要合计行, 则需要标识, summary或缩写s: [合计]行是模板中表格的第几行   summaryfilter或缩写sf:数据集进一步filter到summary行的条件(因为一个表格只取一个Datatable,通过一个标识指定了哪些datarow是用来作为合计的)

D.图表

同样为了方便将配置写在了【标题】,图表生成后会将名称修改过来。

配置格式为:chart_级别_取Dataset中的第几张表(从1开始)_filter字段多个用XX隔开(此处不允许有下划线外其他特殊字符, 就用这个XX吧 )_chart名称_是否将Datatable的columnName作为第一行_从datatable第几列开始(列起始为1)_截止列,

如下图所示配置即可。

 

E.目录

无需标识, 模板中添加目录, 当内容处理完成之后, 会根据处理后的结果动态更新目录.

 

四、主要代码

  1. 1 using System;
  2. 2 using System.Collections.Generic;
  3. 3 using System.Data;
  4. 4 using System.Diagnostics;
  5. 5 using System.IO;
  6. 6 using System.Linq;
  7. 7 using System.Reflection;
  8. 8 using Excel = Microsoft.Office.Interop.Excel;
  9. 9 using Word = Microsoft.Office.Interop.Word;
  10. 10
  11. 11 namespace FlyLolo.WordReport.Demo
  12. 12 {
  13. 13 public class WordReportHelper
  14. 14 {
  15. 15 private Word.Application wordApp = null;
  16. 16 private Word.Document wordDoc = null;
  17. 17 private DataSet dataSource = null;
  18. 18 private object line = Word.WdUnits.wdLine;
  19. 19 private string errorMsg = "";
  20. 20
  21. 21 /// <summary>
  22. 22 /// 根据模板文件,创建数据报告
  23. 23 /// </summary>
  24. 24 /// <param name="templateFile">模板文件名(含路径)</param>
  25. 25 /// <param name="newFilePath">新文件路径)</param>
  26. 26 /// <param name="dataSource">数据源,包含多个datatable</param>
  27. 27 /// <param name="saveFormat">新文件格式:</param>
  28. 28 public bool CreateReport(string templateFile, DataSet dataSource, out string errorMsg, string newFilePath, ref string newFileName, int saveFormat = 16)
  29. 29 {
  30. 30 this.dataSource = dataSource;
  31. 31 errorMsg = this.errorMsg;
  32. 32 bool rtn = OpenTemplate(templateFile)
  33. 33 && SetContent(new WordElement(wordDoc.Range(), dataRow: dataSource.Tables[dataSource.Tables.Count - 1].Rows[0]))
  34. 34 && UpdateTablesOfContents()
  35. 35 && SaveFile(newFilePath, ref newFileName, saveFormat);
  36. 36
  37. 37 CloseAndClear();
  38. 38 return rtn;
  39. 39 }
  40. 40
  41. 41 /// <summary>
  42. 42 /// 打开模板文件
  43. 43 /// </summary>
  44. 44 /// <param name="templateFile"></param>
  45. 45 /// <returns></returns>
  46. 46 private bool OpenTemplate(string templateFile)
  47. 47 {
  48. 48 if (!File.Exists(templateFile))
  49. 49 {
  50. 50 return false;
  51. 51 }
  52. 52
  53. 53 wordApp = new Word.Application();
  54. 54 wordApp.Visible = true;//使文档可见,调试用
  55. 55 wordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
  56. 56 object file = templateFile;
  57. 57 wordDoc = wordApp.Documents.Open(ref file, ReadOnly: false);
  58. 58 return true;
  59. 59 }
  60. 60
  61. 61 /// <summary>
  62. 62 /// 为指定区域写入数据
  63. 63 /// </summary>
  64. 64 /// <param name="element"></param>
  65. 65 /// <returns></returns>
  66. 66 private bool SetContent(WordElement element)
  67. 67 {
  68. 68 string currBookMarkName = string.Empty;
  69. 69 string startWith = "loop_" + (element.Level + 1).ToString() + "_";
  70. 70 foreach (Word.Bookmark item in element.Range.Bookmarks)
  71. 71 {
  72. 72 currBookMarkName = item.Name;
  73. 73
  74. 74 if (currBookMarkName.StartsWith(startWith) && (!currBookMarkName.Equals(element.ElementName)))
  75. 75 {
  76. 76 SetLoop(new WordElement(item.Range, currBookMarkName, element.DataRow, element.GroupBy));
  77. 77 }
  78. 78
  79. 79 }
  80. 80
  81. 81 SetLabel(element);
  82. 82
  83. 83 SetTable(element);
  84. 84
  85. 85 SetChart(element);
  86. 86
  87. 87 return true;
  88. 88 }
  89. 89
  90. 90 /// <summary>
  91. 91 /// 处理循环
  92. 92 /// </summary>
  93. 93 /// <param name="element"></param>
  94. 94 /// <returns></returns>
  95. 95 private bool SetLoop(WordElement element)
  96. 96 {
  97. 97 DataRow[] dataRows = dataSource.Tables[element.TableIndex].Select(element.GroupByString);
  98. 98 int count = dataRows.Count();
  99. 99 element.Range.Select();
  100. 100
  101. 101 //第0行作为模板 先从1开始 循环后处理0行;
  102. 102 for (int i = 0; i < count; i++)
  103. 103 {
  104. 104
  105. 105 element.Range.Copy(); //模板loop复制
  106. 106 wordApp.Selection.InsertParagraphAfter();//换行 不会清除选中的内容,TypeParagraph 等同于回车,若当前有选中内容会被清除. TypeParagraph 会跳到下一行,InsertParagraphAfter不会, 所以movedown一下.
  107. 107 wordApp.Selection.MoveDown(ref line, Missing.Value, Missing.Value);
  108. 108 wordApp.Selection.Paste(); //换行后粘贴复制内容
  109. 109 int offset = wordApp.Selection.Range.End - element.Range.End; //计算偏移量
  110. 110
  111. 111 //复制书签,书签名 = 模板书签名 + 复制次数
  112. 112 foreach (Word.Bookmark subBook in element.Range.Bookmarks)
  113. 113 {
  114. 114 if (subBook.Name.Equals(element.ElementName))
  115. 115 {
  116. 116 continue;
  117. 117 }
  118. 118
  119. 119 wordApp.Selection.Bookmarks.Add(subBook.Name + "_" + i.ToString(), wordDoc.Range(subBook.Start + offset, subBook.End + offset));
  120. 120 }
  121. 121
  122. 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. 123 }
  124. 124
  125. 125 element.Range.Delete();
  126. 126
  127. 127 return true;
  128. 128 }
  129. 129
  130. 130 /// <summary>
  131. 131 /// 处理简单Label
  132. 132 /// </summary>
  133. 133 /// <param name="element"></param>
  134. 134 /// <returns></returns>
  135. 135 private bool SetLabel(WordElement element)
  136. 136 {
  137. 137 if (element.Range.Bookmarks != null && element.Range.Bookmarks.Count > 0)
  138. 138 {
  139. 139 string startWith = "label_" + element.Level.ToString() + "_";
  140. 140 string bookMarkName = string.Empty;
  141. 141 foreach (Word.Bookmark item in element.Range.Bookmarks)
  142. 142 {
  143. 143 bookMarkName = item.Name;
  144. 144
  145. 145 if (bookMarkName.StartsWith(startWith))
  146. 146 {
  147. 147 bookMarkName = WordElement.GetName(bookMarkName);
  148. 148
  149. 149 item.Range.Text = element.DataRow[bookMarkName].ToString();
  150. 150 }
  151. 151 }
  152. 152 }
  153. 153
  154. 154 return true;
  155. 155 }
  156. 156
  157. 157 /// <summary>
  158. 158 /// 填充Table
  159. 159 /// </summary>
  160. 160 /// <param name="element"></param>
  161. 161 /// <returns></returns>
  162. 162 private bool SetTable(WordElement element)
  163. 163 {
  164. 164 if (element.Range.Tables != null && element.Range.Tables.Count > 0)
  165. 165 {
  166. 166 string startWith = "table_" + element.Level.ToString() + "_";
  167. 167 foreach (Word.Table table in element.Range.Tables)
  168. 168 {
  169. 169 if (!string.IsNullOrEmpty(table.Title) && table.Title.StartsWith(startWith))
  170. 170 {
  171. 171 WordElement tableElement = new WordElement(null, table.Title, element.DataRow);
  172. 172
  173. 173 TableConfig config = new TableConfig(table.Descr);
  174. 174
  175. 175 object dataRowTemplate = table.Rows[config.DataRow];
  176. 176 Word.Row SummaryRow = null;
  177. 177 DataRow SummaryDataRow = null;
  178. 178 DataTable dt = dataSource.Tables[tableElement.TableIndex];
  179. 179 DataRow[] dataRows = dataSource.Tables[tableElement.TableIndex].Select(tableElement.GroupByString); ;
  180. 180
  181. 181 if (config.SummaryRow > 0)
  182. 182 {
  183. 183 SummaryRow = table.Rows[config.SummaryRow];
  184. 184 SummaryDataRow = dt.Select(string.IsNullOrEmpty(tableElement.GroupByString) ? config.SummaryFilter : tableElement.GroupByString + " and " + config.SummaryFilter).FirstOrDefault();
  185. 185 }
  186. 186
  187. 187 foreach (DataRow row in dataRows)
  188. 188 {
  189. 189 if (row == SummaryDataRow)
  190. 190 {
  191. 191 continue;
  192. 192 }
  193. 193
  194. 194 Word.Row newRow = table.Rows.Add(ref dataRowTemplate);
  195. 195 for (int j = 0; j < table.Columns.Count; j++)
  196. 196 {
  197. 197 newRow.Cells[j + 1].Range.Text = row[j].ToString(); ;
  198. 198 }
  199. 199
  200. 200 }
  201. 201
  202. 202 ((Word.Row)dataRowTemplate).Delete();
  203. 203
  204. 204 if (config.SummaryRow > 0 && SummaryDataRow != null)
  205. 205 {
  206. 206 for (int j = 0; j < SummaryRow.Cells.Count; j++)
  207. 207 {
  208. 208 string temp = SummaryRow.Cells[j + 1].Range.Text.Trim().Replace("\r\a", "");
  209. 209
  210. 210 if (!string.IsNullOrEmpty(temp) && temp.Length > 2 && dt.Columns.Contains(temp.Substring(1, temp.Length - 2)))
  211. 211 {
  212. 212 SummaryRow.Cells[j + 1].Range.Text = SummaryDataRow[temp.Substring(1, temp.Length - 2)].ToString();
  213. 213 }
  214. 214 }
  215. 215 }
  216. 216
  217. 217 table.Title = tableElement.Name;
  218. 218 }
  219. 219
  220. 220
  221. 221 }
  222. 222 }
  223. 223
  224. 224 return true;
  225. 225 }
  226. 226
  227. 227 /// <summary>
  228. 228 /// 处理图表
  229. 229 /// </summary>
  230. 230 /// <param name="element"></param>
  231. 231 /// <returns></returns>
  232. 232 private bool SetChart(WordElement element)
  233. 233 {
  234. 234 if (element.Range.InlineShapes != null && element.Range.InlineShapes.Count > 0)
  235. 235 {
  236. 236 List<Word.InlineShape> chartList = element.Range.InlineShapes.Cast<Word.InlineShape>().Where(m => m.Type == Word.WdInlineShapeType.wdInlineShapeChart).ToList();
  237. 237 string startWith = "chart_" + element.Level.ToString() + "_";
  238. 238 foreach (Word.InlineShape item in chartList)
  239. 239 {
  240. 240 Word.Chart chart = item.Chart;
  241. 241 if (!string.IsNullOrEmpty(chart.ChartTitle.Text) && chart.ChartTitle.Text.StartsWith(startWith))
  242. 242 {
  243. 243 WordElement chartElement = new WordElement(null, chart.ChartTitle.Text, element.DataRow);
  244. 244
  245. 245 DataTable dataTable = dataSource.Tables[chartElement.TableIndex];
  246. 246 DataRow[] dataRows = dataTable.Select(chartElement.GroupByString);
  247. 247
  248. 248 int columnCount = dataTable.Columns.Count;
  249. 249 List<int> columns = new List<int>();
  250. 250
  251. 251 foreach (var dr in dataRows)
  252. 252 {
  253. 253 for (int i = chartElement.ColumnStart == -1 ? 0 : chartElement.ColumnStart - 1; i < (chartElement.ColumnEnd == -1 ? columnCount : chartElement.ColumnEnd); i++)
  254. 254 {
  255. 255 if (columns.Contains(i) || dr[i] == null || string.IsNullOrEmpty(dr[i].ToString()))
  256. 256 {
  257. 257
  258. 258 }
  259. 259 else
  260. 260 {
  261. 261 columns.Add(i);
  262. 262 }
  263. 263 }
  264. 264 }
  265. 265 columns.Sort();
  266. 266 columnCount = columns.Count;
  267. 267 int rowsCount = dataRows.Length;
  268. 268
  269. 269 Word.ChartData chartData = chart.ChartData;
  270. 270
  271. 271 //chartData.Activate();
  272. 272 //此处有个比较疑惑的问题, 不执行此条,生成的报告中的图表无法再次右键编辑数据. 执行后可以, 但有两个问题就是第一会弹出Excel框, 处理完后会自动关闭. 第二部分chart的数据range设置总不对
  273. 273 //不知道是不是版本的问题, 谁解决了分享一下,谢谢
  274. 274
  275. 275 Excel.Workbook dataWorkbook = (Excel.Workbook)chartData.Workbook;
  276. 276 dataWorkbook.Application.Visible = false;
  277. 277
  278. 278 Excel.Worksheet dataSheet = (Excel.Worksheet)dataWorkbook.Worksheets[1];
  279. 279 //设定范围
  280. 280 string a = (chartElement.ColumnNameForHead ? rowsCount + 1 : rowsCount) + "|" + columnCount;
  281. 281 Console.WriteLine(a);
  282. 282
  283. 283 Excel.Range tRange = dataSheet.Range["A1", dataSheet.Cells[(chartElement.ColumnNameForHead ? rowsCount + 1 : rowsCount), columnCount]];
  284. 284 Excel.ListObject tbl1 = dataSheet.ListObjects[1];
  285. 285 //dataSheet.ListObjects[1].Delete(); //想过重新删除再添加 这样 原有数据清掉了, 但觉得性能应该会有所下降
  286. 286 //Excel.ListObject tbl1 = dataSheet.ListObjects.AddEx();
  287. 287 tbl1.Resize(tRange);
  288. 288 for (int j = 0; j < rowsCount; j++)
  289. 289 {
  290. 290 DataRow row = dataRows[j];
  291. 291 for (int k = 0; k < columnCount; k++)
  292. 292 {
  293. 293 dataSheet.Cells[j + 2, k + 1].FormulaR1C1 = row[columns[k]];
  294. 294 }
  295. 295 }
  296. 296
  297. 297 if (chartElement.ColumnNameForHead)
  298. 298 {
  299. 299 for (int k = 0; k < columns.Count; k++)
  300. 300 {
  301. 301 dataSheet.Cells[1, k + 1].FormulaR1C1 = dataTable.Columns[columns[k]].ColumnName;
  302. 302 }
  303. 303 }
  304. 304 chart.ChartTitle.Text = chartElement.Name;
  305. 305 //dataSheet.Application.Quit();
  306. 306 }
  307. 307 }
  308. 308 }
  309. 309
  310. 310 return true;
  311. 311 }
  312. 312
  313. 313 /// <summary>
  314. 314 /// 更新目录
  315. 315 /// </summary>
  316. 316 /// <returns></returns>
  317. 317 private bool UpdateTablesOfContents()
  318. 318 {
  319. 319 foreach (Word.TableOfContents item in wordDoc.TablesOfContents)
  320. 320 {
  321. 321 item.Update();
  322. 322 }
  323. 323
  324. 324 return true;
  325. 325 }
  326. 326
  327. 327 /// <summary>
  328. 328 /// 保存文件
  329. 329 /// </summary>
  330. 330 /// <param name="newFilePath"></param>
  331. 331 /// <param name="newFileName"></param>
  332. 332 /// <param name="saveFormat"></param>
  333. 333 /// <returns></returns>
  334. 334 private bool SaveFile(string newFilePath, ref string newFileName, int saveFormat = 16)
  335. 335 {
  336. 336 if (string.IsNullOrEmpty(newFileName))
  337. 337 {
  338. 338 newFileName = DateTime.Now.ToString("yyyyMMddHHmmss");
  339. 339
  340. 340 switch (saveFormat)
  341. 341 {
  342. 342 case 0:// Word.WdSaveFormat.wdFormatDocument
  343. 343 newFileName += ".doc";
  344. 344 break;
  345. 345 case 16:// Word.WdSaveFormat.wdFormatDocumentDefault
  346. 346 newFileName += ".docx";
  347. 347 break;
  348. 348 case 17:// Word.WdSaveFormat.wdFormatPDF
  349. 349 newFileName += ".pdf";
  350. 350 break;
  351. 351 default:
  352. 352 break;
  353. 353 }
  354. 354 }
  355. 355
  356. 356 object newfile = Path.Combine(newFilePath, newFileName);
  357. 357 object wdSaveFormat = saveFormat;
  358. 358 wordDoc.SaveAs(ref newfile, ref wdSaveFormat);
  359. 359 return true;
  360. 360 }
  361. 361
  362. 362 /// <summary>
  363. 363 /// 清理
  364. 364 /// </summary>
  365. 365 private void CloseAndClear()
  366. 366 {
  367. 367 if (wordApp == null)
  368. 368 {
  369. 369 return;
  370. 370 }
  371. 371 wordDoc.Close(Word.WdSaveOptions.wdDoNotSaveChanges);
  372. 372 wordApp.Quit(Word.WdSaveOptions.wdDoNotSaveChanges);
  373. 373 System.Runtime.InteropServices.Marshal.ReleaseComObject(wordDoc);
  374. 374 System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
  375. 375 wordDoc = null;
  376. 376 wordApp = null;
  377. 377 GC.Collect();
  378. 378 KillProcess("Excel", "WINWORD");
  379. 379 }
  380. 380
  381. 381 /// <summary>
  382. 382 /// 杀进程..
  383. 383 /// </summary>
  384. 384 /// <param name="processNames"></param>
  385. 385 private void KillProcess(params string[] processNames)
  386. 386 {
  387. 387 //Process myproc = new Process();
  388. 388 //得到所有打开的进程
  389. 389 try
  390. 390 {
  391. 391 foreach (string name in processNames)
  392. 392 {
  393. 393 foreach (Process thisproc in Process.GetProcessesByName(name))
  394. 394 {
  395. 395 if (!thisproc.CloseMainWindow())
  396. 396 {
  397. 397 if (thisproc != null)
  398. 398 thisproc.Kill();
  399. 399 }
  400. 400 }
  401. 401 }
  402. 402 }
  403. 403 catch (Exception)
  404. 404 {
  405. 405 //throw Exc;
  406. 406 // msg.Text+= "杀死" + processName + "失败!";
  407. 407 }
  408. 408 }
  409. 409 }
  410. 410
  411. 411 /// <summary>
  412. 412 /// 封装的Word元素
  413. 413 /// </summary>
  414. 414 public class WordElement
  415. 415 {
  416. 416 public WordElement(Word.Range range, string elementName = "", DataRow dataRow = null, Dictionary<string, string> groupBy = null, int tableIndex = 0)
  417. 417 {
  418. 418 this.Range = range;
  419. 419 this.ElementName = elementName;
  420. 420 this.GroupBy = groupBy;
  421. 421 this.DataRow = dataRow;
  422. 422 if (string.IsNullOrEmpty(elementName))
  423. 423 {
  424. 424 this.Level = 0;
  425. 425 this.TableIndex = tableIndex;
  426. 426 this.Name = string.Empty;
  427. 427 this.ColumnNameForHead = false;
  428. 428 }
  429. 429 else
  430. 430 {
  431. 431 string[] element = elementName.Split('_');
  432. 432 this.Level = int.Parse(element[1]);
  433. 433 this.ColumnNameForHead = false;
  434. 434 this.ColumnStart = -1;
  435. 435 this.ColumnEnd = -1;
  436. 436
  437. 437 if (element[0].Equals("label"))
  438. 438 {
  439. 439 this.Name = element[2];
  440. 440 this.TableIndex = 0;
  441. 441 }
  442. 442 else
  443. 443 {
  444. 444 this.Name = element[4];
  445. 445 this.TableIndex = int.Parse(element[2]) - 1;
  446. 446
  447. 447 if (!string.IsNullOrEmpty(element[3]))
  448. 448 {
  449. 449 string[] filters = element[3].Split(new string[] { "XX" }, StringSplitOptions.RemoveEmptyEntries);
  450. 450 if (this.GroupBy == null)
  451. 451 {
  452. 452 this.GroupBy = new Dictionary<string, string>();
  453. 453 }
  454. 454 foreach (string item in filters)
  455. 455 {
  456. 456 if (!this.GroupBy.Keys.Contains(item))
  457. 457 {
  458. 458 this.GroupBy.Add(item, dataRow[item].ToString());
  459. 459 }
  460. 460
  461. 461 }
  462. 462 }
  463. 463
  464. 464 if (element[0].Equals("chart") && element.Count() > 5)
  465. 465 {
  466. 466 this.ColumnNameForHead = element[5].Equals("1");
  467. 467 this.ColumnStart = string.IsNullOrEmpty(element[6]) ? -1 : int.Parse(element[6]);
  468. 468 this.ColumnEnd = string.IsNullOrEmpty(element[7]) ? -1 : int.Parse(element[7]);
  469. 469 }
  470. 470 }
  471. 471 }
  472. 472 }
  473. 473
  474. 474 public Word.Range Range { get; set; }
  475. 475 public int Level { get; set; }
  476. 476 public int TableIndex { get; set; }
  477. 477 public string ElementName { get; set; }
  478. 478
  479. 479 public DataRow DataRow { get; set; }
  480. 480 public Dictionary<string, string> GroupBy { get; set; }
  481. 481
  482. 482 public string Name { get; set; }
  483. 483
  484. 484 public bool ColumnNameForHead { get; set; }
  485. 485 public int ColumnStart { get; set; }
  486. 486 public int ColumnEnd { get; set; }
  487. 487
  488. 488 public string GroupByString
  489. 489 {
  490. 490 get
  491. 491 {
  492. 492 if (GroupBy == null || GroupBy.Count == 0)
  493. 493 {
  494. 494 return string.Empty;
  495. 495 }
  496. 496
  497. 497 string rtn = string.Empty;
  498. 498 foreach (string key in this.GroupBy.Keys)
  499. 499 {
  500. 500 rtn += "and " + key + " = '" + GroupBy[key] + "' ";
  501. 501 }
  502. 502 return rtn.Substring(3);
  503. 503 }
  504. 504 }
  505. 505
  506. 506 public static string GetName(string elementName)
  507. 507 {
  508. 508 string[] element = elementName.Split('_');
  509. 509
  510. 510
  511. 511 if (element[0].Equals("label"))
  512. 512 {
  513. 513 return element[2];
  514. 514 }
  515. 515 else
  516. 516 {
  517. 517 return element[4];
  518. 518 }
  519. 519 }
  520. 520 }
  521. 521
  522. 522 /// <summary>
  523. 523 /// Table配置项
  524. 524 /// </summary>
  525. 525 public class TableConfig
  526. 526 {
  527. 527 public TableConfig(string tableDescr = "")
  528. 528 {
  529. 529 this.DataRow = 2;
  530. 530 this.SummaryRow = -1;
  531. 531
  532. 532 if (!string.IsNullOrEmpty(tableDescr))
  533. 533 {
  534. 534 string[] element = tableDescr.Split(',');
  535. 535 foreach (string item in element)
  536. 536 {
  537. 537 if (!string.IsNullOrEmpty(item))
  538. 538 {
  539. 539 string[] configs = item.Split(':');
  540. 540 if (configs.Length == 2)
  541. 541 {
  542. 542 switch (configs[0].ToLower())
  543. 543 {
  544. 544 case "data":
  545. 545 case "d":
  546. 546 this.DataRow = int.Parse(configs[1]);
  547. 547 break;
  548. 548 case "summary":
  549. 549 case "s":
  550. 550 this.SummaryRow = int.Parse(configs[1]);
  551. 551 break;
  552. 552 case "summaryfilter":
  553. 553 case "sf":
  554. 554 this.SummaryFilter = configs[1];
  555. 555 break;
  556. 556 default:
  557. 557 break;
  558. 558 }
  559. 559 }
  560. 560 }
  561. 561 }
  562. 562 }
  563. 563
  564. 564 }
  565. 565 public int DataRow { get; set; }
  566. 566 public int SummaryRow { get; set; }
  567. 567 public string SummaryFilter { get; set; }
  568. 568 }
  569. 569 }
View Code

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号