当前位置: 首页 > news >正文

义乌网站建设软件开发招生网站建设方案

义乌网站建设软件开发,招生网站建设方案,北京大企业公司排名,网页设计技术学什么将很早之前写的一个小组件重新整理优化一下#xff0c;做成一个通用的功能。适用于导出数据库的结构#xff08;表、字段等#xff09;到Word或将体检数据自动生成Word版的体检报告等。代码#xff1a;Github 一、主要需要完成功能: 1. 灵活的配置规则及word样式设置#…        将很早之前写的一个小组件重新整理优化一下做成一个通用的功能。适用于导出数据库的结构表、字段等到Word或将体检数据自动生成Word版的体检报告等。代码Github 一、主要需要完成功能: 1. 灵活的配置规则及word样式设置文本、表格、图表、颜色等. 2. 支持表格. 3. 支持图表. 4. 支持章节内容循环生成. 5. 支持目录. 6.支持文档结构图 7.更新指定位置的文字 8.支持pdf导出.   最后结果如下:                                                                             图一                                     图二                                          图三 二、需求分析与实现方式    功能主要涉及3个比较重要的部分数据源、Word样式、配置规则。       为了简单,数据源决定采用一个存储过程返回Dataset的方式, 整张报告的数据来源于此Dataset的多个Datatable.   样式与配置首先想到的是写一个config文件所有配置都放到一个文件里然后将数据按照这个规则生成word。但无疑这样的配置项太多了关键是“样式”问题比如字体、颜色、表格宽度.....想想就头大。而且没有“所见即所得”的效果配置完都不知道啥样。 后来决定采取修改的方式, 先以一个word文件作为模板在模板中定义好上面提到的“样式”然后在模板中做一个个标记然后将数据按照规则更新到对应的标记。                                                        图四     而这个标记我们用到了word的一个叫【书签】的功能打开word按ctrlshiftF5, 打开书签功能如下图                                  图五 这样将【规则】通过一系列规则的【书签】定义到word模板中。 三、规则配置   思路确定了那就开始设计如何通过【书签】将规则定义到word模板中去这里决定将所有规则都通过【书签】实现而放弃config文件的方式这个更统一而且直观一些。 A.循环       以图四为例数据库有多少张表是不固定的我们在制作模板的时候不可能先画好NN为表的总数个表格等待数据填充 这里就会需要遍历数据源中提供的所有表结构数据然后逐一形成表格。这里就需要将图四中的表格循环一下自动复制生成多个这样的表格。当然这只是一种情况还有可能会出现循环嵌套循环的情况那么我将这个循环定义成一个书签的时候按照这样的格式       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 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.Demo12 {13 public class WordReportHelper14 {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 /// summary22 /// 根据模板文件,创建数据报告23 /// /summary24 /// param nametemplateFile模板文件名(含路径)/param25 /// param namenewFilePath新文件路径)/param26 /// param namedataSource数据源,包含多个datatable/param27 /// param namesaveFormat新文件格式:/param28 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 /// summary42 /// 打开模板文件43 /// /summary44 /// param nametemplateFile/param45 /// returns/returns46 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 /// summary62 /// 为指定区域写入数据63 /// /summary64 /// param nameelement/param65 /// returns/returns66 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 /// summary91 /// 处理循环92 /// /summary93 /// param nameelement/param94 /// returns/returns95 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 /// summary 131 /// 处理简单Label 132 /// /summary 133 /// param nameelement/param 134 /// returns/returns 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 /// summary 158 /// 填充Table 159 /// /summary 160 /// param nameelement/param 161 /// returns/returns 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 /// summary 228 /// 处理图表 229 /// /summary 230 /// param nameelement/param 231 /// returns/returns 232 private bool SetChart(WordElement element) 233 { 234 if (element.Range.InlineShapes ! null element.Range.InlineShapes.Count 0) 235 { 236 ListWord.InlineShape chartList element.Range.InlineShapes.CastWord.InlineShape().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 Listint columns new Listint(); 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 /// summary 314 /// 更新目录 315 /// /summary 316 /// returns/returns 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 /// summary 328 /// 保存文件 329 /// /summary 330 /// param namenewFilePath/param 331 /// param namenewFileName/param 332 /// param namesaveFormat/param 333 /// returns/returns 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 /// summary 363 /// 清理 364 /// /summary 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 /// summary 382 /// 杀进程.. 383 /// /summary 384 /// param nameprocessNames/param 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 /// summary 412 /// 封装的Word元素 413 /// /summary 414 public class WordElement 415 { 416 public WordElement(Word.Range range, string elementName , DataRow dataRow null, Dictionarystring, string 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 Dictionarystring, string(); 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 Dictionarystring, string 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 /// summary 523 /// Table配置项 524 /// /summary 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 } View Code  转载于:https://www.cnblogs.com/FlyLolo/p/WordReport.html
http://www.zqtcl.cn/news/485832/

相关文章:

  • 南皮网站建设价格网络推广这个工作好做吗
  • 长安大学门户网站是谁给做的网站排名logo怎么做
  • 襄樊做网站做网站做网站
  • 百度做网站续费费用网站开发的可行性
  • 电子商务网站建设效益分析如何才能做好品牌网站建设策划
  • 能打开各种网站的浏览器app文章目录wordpress
  • 网站注册页面html中国建设招标网网站
  • 云南网站设计海外直购网站建设方案书范文
  • 网站视频小程序商城多少钱
  • 美耐皿 技术支持 东莞网站建设如何将网站指向404
  • 如何做网站的维护和推广wordpress首页在哪里修改
  • 网站建设公司在哪里宣传网站群系统建设的目的
  • 建立网站的教学书籍最新网站建设哪家公司好
  • 视频网站开发者工具科技网站新版网站上线
  • 网站设计简单网页百度提交网站
  • 建设企业网站网站崩溃西安百度网站快速排名
  • 前端 国外 网站请人做网站得多少钱
  • 微商如何做网站引流上海市有哪些公司
  • 服务类型网站开发需要哪些技术中国设计师网效果图
  • 电子商务网站建设技术有哪些方面做婚礼请柬的网站有哪些
  • 做暖暖欧美网站全国职工素质建设工程专题网站
  • 策划对于企业网站建设来说网站开发新加坡
  • 做仪表行业推广有哪些网站个人网站备案模板
  • 做微网站是订阅号还是服务号号网站建设叫什么软件
  • 美团初期是怎么建网站特效视频素材网站
  • 网站建设行业市场分析刚创业 建网站
  • 网站推广昔年下拉wordpress 首页添加链接地址
  • 网站年费推荐专业做网站公司
  • 邵东微网站建设设计网页图片
  • 沈阳高端做网站建设应用软件商店