@@ -3,6 +3,7 @@ import { ExcelStrings } from './excel-strings';
33import { WorksheetData } from './worksheet-data' ;
44
55import * as JSZip from 'jszip' ;
6+ import { yieldingLoop } from '../../core/utils' ;
67
78/**
89 * @hidden
@@ -55,6 +56,10 @@ export class ThemeFile implements IExcelFile {
5556 */
5657export class WorksheetFile implements IExcelFile {
5758 private static MIN_WIDTH = 8.34 ;
59+ private maxOutlineLevel = 0 ;
60+ private dimension = '' ;
61+ private freezePane = '' ;
62+ private rowHeight = '' ;
5863
5964 public writeElement ( folder : JSZip , worksheetData : WorksheetData ) {
6065 const sheetData = [ ] ;
@@ -131,6 +136,104 @@ export class WorksheetFile implements IExcelFile {
131136 worksheetData . isTreeGridData , maxOutlineLevel ) ) ;
132137 }
133138
139+ public writeElementAsync ( folder : JSZip , worksheetData : WorksheetData , done : ( ) => void ) {
140+ this . prepareDataAsync ( worksheetData , ( cols , rows ) => {
141+ const hasTable = ! worksheetData . isEmpty && worksheetData . options . exportAsTable ;
142+ folder . file ( 'sheet1.xml' , ExcelStrings . getSheetXML (
143+ this . dimension , this . freezePane , cols , rows , hasTable , worksheetData . isTreeGridData , this . maxOutlineLevel ) ) ;
144+ done ( ) ;
145+ } ) ;
146+ }
147+
148+ private prepareDataAsync ( worksheetData : WorksheetData , done : ( cols : string , rows : string ) => void ) {
149+ let sheetData = '' ;
150+ let cols = '' ;
151+ const dictionary = worksheetData . dataDictionary ;
152+
153+ if ( worksheetData . isEmpty ) {
154+ sheetData += '<sheetData/>' ;
155+ this . dimension = 'A1' ;
156+ } else {
157+ sheetData += '<sheetData>' ;
158+ const height = worksheetData . options . rowHeight ;
159+ this . rowHeight = height ? ' ht="' + height + '" customHeight="1"' : '' ;
160+ sheetData += `<row r="1"${ this . rowHeight } >` ;
161+
162+ for ( let i = 0 ; i < worksheetData . columnCount ; i ++ ) {
163+ const column = ExcelStrings . getExcelColumn ( i ) + 1 ;
164+ const value = dictionary . saveValue ( worksheetData . keys [ i ] , i , true ) ;
165+ sheetData += `<c r="${ column } " t="s"><v>${ value } </v></c>` ;
166+ }
167+ sheetData += '</row>' ;
168+
169+ this . dimension = 'A1:' + ExcelStrings . getExcelColumn ( worksheetData . columnCount - 1 ) + worksheetData . rowCount ;
170+ cols += '<cols>' ;
171+
172+ for ( let i = 0 ; i < worksheetData . columnCount ; i ++ ) {
173+ const width = dictionary . columnWidths [ i ] ;
174+ // Use the width provided in the options if it exists
175+ const widthInTwips = worksheetData . options . columnWidth ?
176+ worksheetData . options . columnWidth :
177+ Math . max ( ( ( width / 96 ) * 14.4 ) , WorksheetFile . MIN_WIDTH ) ;
178+
179+ cols += `<col min="${ ( i + 1 ) } " max="${ ( i + 1 ) } " width="${ widthInTwips } " customWidth="1"/>` ;
180+ }
181+
182+ cols += '</cols>' ;
183+
184+ if ( worksheetData . indexOfLastPinnedColumn !== - 1 &&
185+ ! worksheetData . options . ignorePinning &&
186+ ! worksheetData . options . ignoreColumnsOrder ) {
187+ const frozenColumnCount = worksheetData . indexOfLastPinnedColumn + 1 ;
188+ const firstCell = ExcelStrings . getExcelColumn ( frozenColumnCount ) + '1' ;
189+ this . freezePane = `<pane xSplit="${ frozenColumnCount } " topLeftCell="${ firstCell } " activePane="topRight" state="frozen"/>` ;
190+ }
191+
192+ this . processDataRecordsAsync ( worksheetData , ( rows ) => {
193+ sheetData += rows ;
194+ sheetData += '</sheetData>' ;
195+ done ( cols , sheetData ) ;
196+ } ) ;
197+ }
198+ }
199+
200+ private processDataRecordsAsync ( worksheetData : WorksheetData , done : ( rows : string ) => void ) {
201+ let dataRecords = '' ;
202+ const height = worksheetData . options . rowHeight ;
203+ this . rowHeight = height ? ' ht="' + height + '" customHeight="1"' : '' ;
204+
205+ yieldingLoop ( worksheetData . rowCount - 1 , 1000 ,
206+ ( i ) => {
207+ dataRecords += this . processRow ( worksheetData , i + 1 ) ;
208+ } ,
209+ ( ) => {
210+ done ( dataRecords ) ;
211+ } ) ;
212+ }
213+
214+ private processRow ( worksheetData : WorksheetData , i : number ) {
215+ const rowData = new Array ( worksheetData . columnCount + 2 ) ;
216+ if ( ! worksheetData . isTreeGridData ) {
217+ rowData [ 0 ] = `<row r="${ ( i + 1 ) } "${ this . rowHeight } >` ;
218+ } else {
219+ const originalData = worksheetData . data [ i ] . originalRowData ;
220+ const sCollapsed = ( ! originalData . expanded ) ? '' : ( originalData . expanded === true ) ? '' : ` collapsed="1"` ;
221+ const sHidden = ( originalData . parent && this . hasCollapsedParent ( originalData ) ) ? ` hidden="1"` : '' ;
222+ const rowOutlineLevel = originalData . level ? originalData . level : 0 ;
223+ const sOutlineLevel = rowOutlineLevel > 0 ? ` outlineLevel="${ rowOutlineLevel } "` : '' ;
224+ this . maxOutlineLevel = this . maxOutlineLevel < rowOutlineLevel ? rowOutlineLevel : this . maxOutlineLevel ;
225+ rowData [ 0 ] = `<row r="${ ( i + 1 ) } "${ this . rowHeight } ${ sOutlineLevel } ${ sCollapsed } ${ sHidden } >` ;
226+ }
227+
228+ for ( let j = 0 ; j < worksheetData . columnCount ; j ++ ) {
229+ const cellData = WorksheetFile . getCellData ( worksheetData , i , j ) ;
230+ rowData [ j + 1 ] = cellData ;
231+ }
232+ rowData [ worksheetData . columnCount + 1 ] = '</row>' ;
233+
234+ return rowData . join ( '' ) ;
235+ }
236+
134237 private hasCollapsedParent ( rowData ) {
135238 let result = ! rowData . parent . expanded ;
136239 while ( rowData . parent ) {
0 commit comments