| 
					
				 | 
			
			
				@@ -2,6 +2,8 @@ class ExportExcel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   workBook = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   sheet = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sheetIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   border = new GC.Spread.Sheets.LineBorder('#000', GC.Spread.Sheets.LineStyle.thin); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -12,14 +14,15 @@ class ExportExcel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 表格当前画到的行 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   curRow = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  billTree = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  curMaxCol = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  curBillNode = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  billTree = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   libID = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // 表格块,类型为ExcelBlock实例 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  blocks = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 分部章节单元格数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sections = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 清单ID - 清单精灵映射 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   billIDElfMap = {}; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -30,10 +33,15 @@ class ExportExcel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 叶子清单总数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   total = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 清单ID - 最大列映射 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  maxColMap = {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 叶子节点的父项ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  leafParentIDs = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   constructor(workBook, billTree, libID) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     this.workBook = workBook; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     this.sheet = this.workBook.getSheet(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    this.initSheet(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     this.billTree = billTree; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     this.libID = libID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     this.leafIDs = billTree.items.filter(node => !node.children.length).map(node => node.data.ID); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -53,59 +61,18 @@ class ExportExcel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         alert(e); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         console.log(e); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 将数据画在表格上 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    async paintOnSheet() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 将数据画在工作簿上 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async paintOnWorkBook() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       this.updateProcessInfo(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // let i = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      this.sheet.suspendPaint(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      this.sheet.suspendEvent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      for (const billNode of this.billTree.items) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // 画标题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (this.curRow >= this.sheet.getRowCount()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          this.sheet.addRows(this.curRow, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.sheet.setFormatter(this.curRow, 0, '@'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.sheet.setFormatter(this.curRow, 1, '@'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.sheet.setText(this.curRow, 0, billNode.data.code); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.sheet.setText(this.curRow++, 1, billNode.data.name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // 画表格 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!billNode.children.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          this.curRow++; // 空行 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          const elfTree = await this.getElfTree(billNode.data.ID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (!elfTree) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          const block = this.getBlock(elfTree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (!block.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          const blockRange = this.getBlockRange(elfTree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          this.checkRange(blockRange); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          const range = this.sheet.getRange(block[0].row + this.curRow, block[0].col, blockRange.rowCount, blockRange.colCount) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          // 画单元格 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          console.log(billNode.data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          console.log(block); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          this.drawCell(block); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          // 画边框 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          this.drawBorder(range) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          // i++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          this.curRow += blockRange.rowCount + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        /* if (i === 100) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const range = this.sheet.getRange(0, 0, this.sheet.getRowCount(), this.sheet.getColumnCount()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      range.vAlign(GC.Spread.Sheets.VerticalAlign.center); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      range.wordWrap(true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      this.sheet.resumeEvent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      this.sheet.resumePaint(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (this.total === this.curProcessCount) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.afterPaint(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 根据专业区分不同sheet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for (const root of this.billTree.roots) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.initSheet(this.sheetIndex++, root.data.name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const nodes = [root, ...root.getPosterity()]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        await this.paintOnSheet(nodes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.afterPaint(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* ========================================================以下为私有方法============================================== */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -115,6 +82,58 @@ class ExportExcel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return this.total - this.leafIDs.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 将数据画在表格上 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  async paintOnSheet(nodes) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.updateProcessInfo(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let i = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.sheet.suspendPaint(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.sheet.suspendEvent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (const billNode of nodes) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (this.curRow >= this.sheet.getRowCount()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.sheet.addRows(this.curRow, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.curMaxCol = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (billNode.children.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 清单分部章节,合并的列数依赖主体表格,所以先存数据画空行,后续再画具体内容 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.sections.push({ ID: billNode.data.ID, isNotLeaf: true, row: this.curRow, col: 0, text: `${billNode.data.code} ${billNode.data.name}`, rowCount: 1, colCount: 1 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.curRow++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!this.leafParentIDs.includes(billNode.data.ParentID)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          this.leafParentIDs.push(billNode.data.ParentID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (this.maxColMap[billNode.data.ParentID] === undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          this.maxColMap[billNode.data.ParentID] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 叶子清单,合并的列数依赖主体表格,所以先存数据画空行,后续再画具体内容 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const billText = `编码:${billNode.data.code}    名称:${billNode.data.name}    单位:${billNode.data.unit}`; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.sections.push({ ID: billNode.data.ID, row: this.curRow, col: 0, text: billText, rowCount: 1, colCount: 1 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.curRow++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 画清单精灵表格 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const elfTree = await this.getElfTree(billNode.data.ID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!elfTree) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.drawBlock(elfTree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (this.maxColMap[billNode.data.ParentID] < this.curMaxCol) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          this.maxColMap[billNode.data.ParentID] = this.curMaxCol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        i++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* if (i === 10) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 画章节 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.drawSection(this.sections); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const range = this.sheet.getRange(0, 0, this.sheet.getRowCount(), this.sheet.getColumnCount()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    range.vAlign(GC.Spread.Sheets.VerticalAlign.center); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    range.wordWrap(true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.sheet.resumeEvent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.sheet.resumePaint(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 画完表格后的处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   afterPaint() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       $('#excel-dialog').width('800px'); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -139,11 +158,20 @@ class ExportExcel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 画单元格、合并单元格 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  drawCell(block) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  drawCell(block, addCurRow) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     block.forEach(item => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const row = item.row + this.curRow; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const row =  addCurRow ? item.row + this.curRow : item.row; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       this.sheet.addSpan(row, item.col, item.rowCount, item.colCount); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       this.sheet.setFormatter(row, item.col, '@'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (item.isTitle) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 标题水平居中,字体加粗 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const range = this.sheet.getRange(row, item.col, 1, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        range.hAlign(GC.Spread.Sheets.VerticalAlign.center); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.sheet.getCell(row, item.col).font('bold normal 15px normal'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (item.isNotLeaf) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const range = this.sheet.getRange(row, item.col, 1, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        range.hAlign(GC.Spread.Sheets.VerticalAlign.center); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       this.sheet.setText(row, item.col, item.text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -158,9 +186,70 @@ class ExportExcel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     this.$info.text(`导出排版中: ${this.curProcessCount} / ${this.total}`) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 完善章节清单ID - 最大列映射 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setSectionMaxCol() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.leafParentIDs.forEach(ID => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const node = this.billTree.findNode(ID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (!node) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      node.children.forEach(child => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.maxColMap[child.data.ID] = this.maxColMap[ID]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      let parent = node.parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      while (parent && this.maxColMap[parent.data.ID] === undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.maxColMap[parent.data.ID] = this.maxColMap[ID]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        parent = parent.parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 画章节 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  drawSection(sections) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setSectionMaxCol(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sections.forEach(section => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const maxCol = this.maxColMap[section.ID] || 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      section.colCount = maxCol + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.drawCell(sections, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 画主体表格 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  async drawBlock(elfTree) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const block = this.getBlock(elfTree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!block.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const blockRange = this.getBlockRange(elfTree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.checkRange(blockRange); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const range = this.sheet.getRange(block[0].row + this.curRow, block[0].col, blockRange.rowCount, blockRange.colCount) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 画单元格 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.drawCell(block, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 画边框 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.drawBorder(range); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.curRow += blockRange.rowCount; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 精灵树数据转换为表格块单元格数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   getBlock(elfTree) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return elfTree.items.map(node => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const block = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 表格正文 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const blockContent = this.getBlockContent(elfTree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 表格标题:获取完正文,才知道标题的合并列数,因此先获取表格正文,再获取表格标题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const blockTitle = this.getBlockTitle(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 表格正文的行号,整体下移 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    blockContent.forEach(cellInfo => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      cellInfo.row += 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    block.push(...blockTitle); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    block.push(...blockContent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return block; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 获取表格块正文单元格数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getBlockContent(elfTree) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const block = elfTree.items.map(node => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // rowCount、colCount标记合并单元格范围 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const rowCount = node.posterityLeafCount() || 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const parentRow = node.parent && node.parent.cellInfo ? node.parent.cellInfo.row : 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -176,25 +265,54 @@ class ExportExcel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         col, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rowCount, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (this.curMaxCol < col) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.curMaxCol = col; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         row, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         col, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         rowCount, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         text, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        isRation: node.data.type === itemType.ration, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         colCount: 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.moveRationTextToLastCol(block); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return block; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 获取表格标题单元格数据,计算标题合并列依赖正文表格 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getBlockTitle() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      { row: 0, col: 0, rowCount: 1, colCount: 1, text: '工序', isTitle: true }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      { row: 0, col: 1, rowCount: 1, colCount: this.curMaxCol === 0 ? 1 : this.curMaxCol - 1, text: '选项', isTitle: true }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      { row: 0, col: this.curMaxCol === 0 ? 2 : this.curMaxCol, rowCount: 1, colCount: 1, text: '定额', isTitle: true }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 将定额文本挪到表格最大列处显示 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  moveRationTextToLastCol(block) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    block.forEach(cellInfo => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (cellInfo.isRation) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cellInfo.col = this.curMaxCol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 从表格中获取最大列号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getMaxCol(block) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return Math.max(...block.map(cellInfo => cellInfo.col)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 根据精灵树数据,获取表格块range 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   getBlockRange(elfTree) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const rowCount = elfTree.roots.reduce((prev, node) => prev + (node.posterityLeafCount() || 1), 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const rowCount = elfTree.roots.reduce((prev, node) => prev + (node.posterityLeafCount() || 1), 0) + 1; // +1是因为有一行标题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const a = Date.now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const colCount = Math.max(...elfTree.items.map(node => node.depth())) + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     console.log(Date.now() - a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       rowCount, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      colCount 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      colCount: colCount === 1 ? 3 : colCount, // 有些表格没有选项和定额 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -228,8 +346,16 @@ class ExportExcel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return this.billIDElfMap[billID]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  initSheet() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    this.sheet.name('清单精灵'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  initSheet(index, name) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.curRow = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.sections = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.leafParentIDs = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (index !== 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 工作簿自身会有一张表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.workBook.addSheet(index); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.sheet = this.workBook.getSheet(index); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.sheet.name(name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for (let col = 0; col < this.sheet.getColumnCount(); col++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       this.sheet.setColumnWidth(col, 100); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 |