66using System . Collections ;
77using System . Collections . Generic ;
88using System . Data ;
9+ using System . Globalization ;
910using System . IO . Compression ;
1011using System . Linq ;
1112using System . Text ;
@@ -104,6 +105,8 @@ private async Task GenerateSheetByIDataReaderAsync(MiniExcelAsyncStreamWriter wr
104105 var yIndex = 1 ;
105106 int maxColumnIndex;
106107 int maxRowIndex;
108+ ExcelWidthCollection widths = null ;
109+ long columnWidthsPlaceholderPosition = 0 ;
107110 {
108111 if ( _configuration . FastMode )
109112 {
@@ -122,7 +125,15 @@ private async Task GenerateSheetByIDataReaderAsync(MiniExcelAsyncStreamWriter wr
122125 //sheet view
123126 await writer . WriteAsync ( GetSheetViews ( ) ) ;
124127
125- await WriteColumnsWidthsAsync ( writer , props ) ;
128+ if ( _configuration . EnableAutoWidth )
129+ {
130+ columnWidthsPlaceholderPosition = await WriteColumnWidthPlaceholdersAsync ( writer , props ) ;
131+ widths = new ExcelWidthCollection ( _configuration . MinWidth , _configuration . MaxWidth , props ) ;
132+ }
133+ else
134+ {
135+ await WriteColumnsWidthsAsync( writer , ExcelColumnWidth . FromProps ( props ) ) ;
136+ }
126137
127138 await writer. WriteAsync ( WorksheetXml . StartSheetData ) ;
128139 int fieldCount = reader. FieldCount ;
@@ -139,7 +150,7 @@ private async Task GenerateSheetByIDataReaderAsync(MiniExcelAsyncStreamWriter wr
139150 for ( int i = 0 ; i < fieldCount ; i ++ )
140151 {
141152 var cellValue = reader. GetValue ( i ) ;
142- await WriteCellAsync ( writer , yIndex , xIndex , cellValue , props [ i ] ) ;
153+ await WriteCellAsync( writer , yIndex , xIndex , cellValue , props [ i ] , widths ) ;
143154 xIndex++ ;
144155 }
145156 await writer. WriteAsync ( WorksheetXml . EndRow ) ;
@@ -163,6 +174,10 @@ private async Task GenerateSheetByIDataReaderAsync(MiniExcelAsyncStreamWriter wr
163174 {
164175 await WriteDimensionAsync ( writer , maxRowIndex , maxColumnIndex , dimensionPlaceholderPostition ) ;
165176 }
177+ if ( _configuration . EnableAutoWidth )
178+ {
179+ await OverWriteColumnWidthPlaceholdersAsync ( writer , columnWidthsPlaceholderPosition , widths . Columns ) ;
180+ }
166181 }
167182
168183 private async Task GenerateSheetByEnumerableAsync(MiniExcelAsyncStreamWriter writer, IEnumerable values)
@@ -248,7 +263,17 @@ private async Task GenerateSheetByEnumerableAsync(MiniExcelAsyncStreamWriter wri
248263 await writer . WriteAsync ( GetSheetViews ( ) ) ;
249264
250265 //cols:width
251- await WriteColumnsWidthsAsync( writer, props) ;
266+ ExcelWidthCollection widths = null ;
267+ long columnWidthsPlaceholderPosition = 0 ;
268+ if ( _configuration . EnableAutoWidth )
269+ {
270+ columnWidthsPlaceholderPosition = await WriteColumnWidthPlaceholdersAsync ( writer , props ) ;
271+ widths = new ExcelWidthCollection ( _configuration . MinWidth , _configuration . MaxWidth , props ) ;
272+ }
273+ else
274+ {
275+ await WriteColumnsWidthsAsync ( writer , ExcelColumnWidth . FromProps ( props ) ) ;
276+ }
252277
253278 //header
254279 await writer . WriteAsync ( WorksheetXml . StartSheetData ) ;
@@ -266,13 +291,13 @@ private async Task GenerateSheetByEnumerableAsync(MiniExcelAsyncStreamWriter wri
266291 switch ( mode )
267292 {
268293 case "IDictionary<string, object>" : //Dapper Row
269- maxRowIndex = await GenerateSheetByColumnInfoAsync< IDictionary< string , object >> ( writer, enumerator, props, xIndex, yIndex) ;
294+ maxRowIndex = await GenerateSheetByColumnInfoAsync < IDictionary < string , object > > ( writer , enumerator , props , widths , xIndex , yIndex ) ;
270295 break ;
271296 case "IDictionary":
272- maxRowIndex = await GenerateSheetByColumnInfoAsync< IDictionary> ( writer, enumerator, props, xIndex, yIndex) ;
297+ maxRowIndex = await GenerateSheetByColumnInfoAsync < IDictionary > ( writer , enumerator , props , widths , xIndex , yIndex ) ;
273298 break ;
274299 case "Properties" :
275- maxRowIndex = await GenerateSheetByColumnInfoAsync< object > ( writer, enumerator, props, xIndex, yIndex) ;
300+ maxRowIndex = await GenerateSheetByColumnInfoAsync < object > ( writer , enumerator , props , widths , xIndex , yIndex ) ;
276301 break ;
277302 default :
278303 throw new NotImplementedException ( $ "Type { values . GetType ( ) . FullName } is not implemented. Please open an issue.") ;
@@ -293,6 +318,10 @@ private async Task GenerateSheetByEnumerableAsync(MiniExcelAsyncStreamWriter wri
293318 {
294319 await WriteDimensionAsync( writer , maxRowIndex , maxColumnIndex , dimensionPlaceholderPostition ) ;
295320 }
321+ if ( _configuration . EnableAutoWidth )
322+ {
323+ await OverWriteColumnWidthPlaceholdersAsync( writer , columnWidthsPlaceholderPosition , widths . Columns ) ;
324+ }
296325 }
297326
298327 private async Task GenerateSheetByDataTableAsync( MiniExcelAsyncStreamWriter writer , DataTable value )
@@ -318,7 +347,17 @@ private async Task GenerateSheetByDataTableAsync(MiniExcelAsyncStreamWriter writ
318347 //sheet view
319348 await writer. WriteAsync( GetSheetViews( ) ) ;
320349
321- await WriteColumnsWidthsAsync ( writer , props ) ;
350+ ExcelWidthCollection widths = null ;
351+ long columnWidthsPlaceholderPosition = 0 ;
352+ if ( _configuration. EnableAutoWidth)
353+ {
354+ columnWidthsPlaceholderPosition = await WriteColumnWidthPlaceholdersAsync( writer, props) ;
355+ widths = new ExcelWidthCollection( _configuration. MinWidth, _configuration. MaxWidth, props) ;
356+ }
357+ else
358+ {
359+ await WriteColumnsWidthsAsync( writer, ExcelColumnWidth. FromProps( props) ) ;
360+ }
322361
323362 await writer. WriteAsync( WorksheetXml. StartSheetData) ;
324363 if ( _printHeader)
@@ -344,7 +383,7 @@ private async Task GenerateSheetByDataTableAsync(MiniExcelAsyncStreamWriter writ
344383 for ( int j = 0 ; j < value. Columns. Count; j++ )
345384 {
346385 var cellValue = value. Rows[ i] [ j] ;
347- await WriteCellAsync ( writer , yIndex , xIndex , cellValue , props [ j ] ) ;
386+ await WriteCellAsync( writer, yIndex, xIndex, cellValue, props[ j] , widths ) ;
348387 xIndex++ ;
349388 }
350389 await writer. WriteAsync( WorksheetXml. EndRow) ;
@@ -357,25 +396,48 @@ private async Task GenerateSheetByDataTableAsync(MiniExcelAsyncStreamWriter writ
357396 {
358397 await writer. WriteAsync( WorksheetXml. Autofilter( GetDimensionRef( maxRowIndex, maxColumnIndex) ) ) ;
359398 }
399+ if ( _configuration. EnableAutoWidth)
400+ {
401+ await OverWriteColumnWidthPlaceholdersAsync( writer, columnWidthsPlaceholderPosition, widths. Columns) ;
402+ }
360403
361404 await writer. WriteAsync( WorksheetXml. EndWorksheet) ;
362405 }
363406
364- private static async Task WriteColumnsWidthsAsync ( MiniExcelAsyncStreamWriter writer , IEnumerable < ExcelColumnInfo > props )
407+ private async Task< long > WriteColumnWidthPlaceholdersAsync ( MiniExcelAsyncStreamWriter writer, ICollection < ExcelColumnInfo> props)
365408 {
366- var ecwProps = props . Where ( x => x ? . ExcelColumnWidth != null ) . ToList ( ) ;
367- if ( ecwProps . Count <= 0 )
368- {
369- return ;
370- }
409+ var placeholderPosition = await writer. FlushAsync( ) ;
410+ await writer. WriteWhitespaceAsync( WorksheetXml. GetColumnPlaceholderLength( props. Count) ) ;
411+ return placeholderPosition;
412+ }
371413
372- await writer . WriteAsync ( WorksheetXml . StartCols ) ;
414+ private async Task OverWriteColumnWidthPlaceholdersAsync( MiniExcelAsyncStreamWriter writer, long placeholderPosition, IEnumerable< ExcelColumnWidth> columnWidths)
415+ {
416+ var position = await writer. FlushAsync( ) ;
373417
374- foreach ( var p in ecwProps )
418+ writer. SetPosition( placeholderPosition) ;
419+ await WriteColumnsWidthsAsync( writer, columnWidths) ;
420+
421+ await writer. FlushAsync( ) ;
422+ writer. SetPosition( position) ;
423+ }
424+
425+ private async Task WriteColumnsWidthsAsync( MiniExcelAsyncStreamWriter writer, IEnumerable< ExcelColumnWidth> columnWidths)
426+ {
427+ var hasWrittenStart = false;
428+ foreach ( var column in columnWidths)
375429 {
376- await writer . WriteAsync ( WorksheetXml . Column ( p . ExcelColumnIndex , p . ExcelColumnWidth ) ) ;
430+ if ( ! hasWrittenStart)
431+ {
432+ await writer. WriteAsync( WorksheetXml. StartCols) ;
433+ hasWrittenStart = true;
434+ }
435+ await writer. WriteAsync( WorksheetXml. Column( column. Index, column. Width) ) ;
436+ }
437+ if ( ! hasWrittenStart)
438+ {
439+ return ;
377440 }
378-
379441 await writer. WriteAsync( WorksheetXml. EndCols) ;
380442 }
381443
@@ -401,7 +463,7 @@ private static async Task PrintHeaderAsync(MiniExcelAsyncStreamWriter writer, Li
401463 await writer. WriteAsync( WorksheetXml. EndRow) ;
402464 }
403465
404- private async Task < int > GenerateSheetByColumnInfoAsync < T > ( MiniExcelAsyncStreamWriter writer , IEnumerator value , List < ExcelColumnInfo > props , int xIndex = 1 , int yIndex = 1 )
466+ private async Task< int > GenerateSheetByColumnInfoAsync< T> ( MiniExcelAsyncStreamWriter writer, IEnumerator value, List< ExcelColumnInfo> props, ExcelWidthCollection widthCollection , int xIndex = 1 , int yIndex = 1 )
405467 {
406468 var isDic = typeof ( T) == typeof ( IDictionary) ;
407469 var isDapperRow = typeof ( T) == typeof ( IDictionary< string , object > ) ;
@@ -436,7 +498,7 @@ private async Task<int> GenerateSheetByColumnInfoAsync<T>(MiniExcelAsyncStreamWr
436498 cellValue = p. Property. GetValue( v) ;
437499 }
438500
439- await WriteCellAsync ( writer , yIndex , cellIndex , cellValue , p ) ;
501+ await WriteCellAsync( writer, yIndex, cellIndex, cellValue, p, widthCollection ) ;
440502
441503 cellIndex++ ;
442504 }
@@ -453,7 +515,7 @@ private static async Task WriteCellAsync(MiniExcelAsyncStreamWriter writer, stri
453515 await writer. WriteAsync( WorksheetXml. Cell( cellReference, "str", "1 ", ExcelOpenXmlUtils. EncodeXML( columnName) ) ) ;
454516 }
455517
456- private async Task WriteCellAsync ( MiniExcelAsyncStreamWriter writer , int rowIndex , int cellIndex , object value , ExcelColumnInfo p )
518+ private async Task WriteCellAsync( MiniExcelAsyncStreamWriter writer, int rowIndex, int cellIndex, object value, ExcelColumnInfo p, ExcelWidthCollection widthCollection )
457519 {
458520 var columnReference = ExcelOpenXmlUtils. ConvertXyToCell( cellIndex, rowIndex) ;
459521 var valueIsNull = value is null || value is DBNull;
@@ -474,6 +536,7 @@ private async Task WriteCellAsync(MiniExcelAsyncStreamWriter writer, int rowInde
474536 /*Prefix and suffix blank space will lost after SaveAs #294*/
475537 var preserveSpace = cellValue != null && ( cellValue. StartsWith( " ", StringComparison. Ordinal) || cellValue. EndsWith( " ", StringComparison. Ordinal) ) ;
476538 await writer. WriteAsync( WorksheetXml. Cell( columnReference, dataType, styleIndex, cellValue, preserveSpace: preserveSpace, columnType: columnType) ) ;
539+ widthCollection? . AdjustWidth( cellIndex, cellValue) ;
477540 }
478541
479542 private async Task GenerateEndXmlAsync( CancellationToken cancellationToken)
0 commit comments