1
1
using MiniExcelLibs . OpenXml . Constants ;
2
+ using MiniExcelLibs . OpenXml . Models ;
3
+ using MiniExcelLibs . OpenXml . Styles ;
2
4
using MiniExcelLibs . Utils ;
3
5
using MiniExcelLibs . Zip ;
4
6
using System ;
@@ -15,7 +17,7 @@ namespace MiniExcelLibs.OpenXml
15
17
{
16
18
internal partial class ExcelOpenXmlSheetWriter : IExcelWriter
17
19
{
18
- public async Task SaveAsAsync ( CancellationToken cancellationToken = default ( CancellationToken ) )
20
+ public async Task SaveAsAsync ( CancellationToken cancellationToken = default )
19
21
{
20
22
await GenerateDefaultOpenXmlAsync ( cancellationToken ) ;
21
23
@@ -32,6 +34,67 @@ internal partial class ExcelOpenXmlSheetWriter : IExcelWriter
32
34
_archive . Dispose ( ) ;
33
35
}
34
36
37
+ public async Task InsertAsync ( bool overwriteSheet = false , CancellationToken cancellationToken = default )
38
+ {
39
+ if ( ! _configuration . FastMode )
40
+ {
41
+ throw new InvalidOperationException ( "Insert requires fast mode to be enabled" ) ;
42
+ }
43
+
44
+ var sheetRecords = new ExcelOpenXmlSheetReader ( _stream , _configuration ) . GetWorkbookRels ( _archive . Entries ) . ToArray ( ) ;
45
+ foreach ( var sheetRecord in sheetRecords . OrderBy ( o => o . Id ) )
46
+ {
47
+ _sheets . Add ( new SheetDto { Name = sheetRecord . Name , SheetIdx = ( int ) sheetRecord . Id , State = sheetRecord . State } ) ;
48
+ }
49
+ var existSheetDto = _sheets . SingleOrDefault ( s => s . Name == _defaultSheetName ) ;
50
+ if ( existSheetDto != null && ! overwriteSheet )
51
+ {
52
+ throw new Exception ( $ "Sheet “{ _defaultSheetName } ” already exist") ;
53
+ }
54
+
55
+ await GenerateStylesXmlAsync ( cancellationToken ) ; //GenerateStylesXml必须在校验overwriteSheet之后,避免不必要的样式更改
56
+
57
+ if ( existSheetDto == null )
58
+ {
59
+ currentSheetIndex = ( int ) sheetRecords . Max ( m => m . Id ) + 1 ;
60
+ var insertSheetInfo = GetSheetInfos ( _defaultSheetName ) ;
61
+ var insertSheetDto = insertSheetInfo . ToDto ( currentSheetIndex ) ;
62
+ _sheets . Add ( insertSheetDto ) ;
63
+ await CreateSheetXmlAsync ( _value , insertSheetDto . Path , cancellationToken ) ;
64
+ }
65
+ else
66
+ {
67
+ currentSheetIndex = existSheetDto . SheetIdx ;
68
+ _archive . Entries . Single ( s => s . FullName == existSheetDto . Path ) . Delete ( ) ;
69
+ _archive . Entries . SingleOrDefault ( s => s . FullName == ExcelFileNames . DrawingRels ( currentSheetIndex ) ) ? . Delete ( ) ;
70
+ _archive . Entries . SingleOrDefault ( s => s . FullName == ExcelFileNames . Drawing ( currentSheetIndex ) ) ? . Delete ( ) ;
71
+ await CreateSheetXmlAsync ( _value , existSheetDto . Path , cancellationToken ) ;
72
+ }
73
+
74
+ await AddFilesToZipAsync ( cancellationToken ) ;
75
+
76
+ await GenerateDrawinRelXmlAsync ( currentSheetIndex , cancellationToken ) ;
77
+
78
+ await GenerateDrawingXmlAsync ( currentSheetIndex , cancellationToken ) ;
79
+
80
+ GenerateWorkBookXmls ( out StringBuilder workbookXml , out StringBuilder workbookRelsXml , out Dictionary < int , string > sheetsRelsXml ) ;
81
+
82
+ foreach ( var sheetRelsXml in sheetsRelsXml )
83
+ {
84
+ var sheetRelsXmlPath = ExcelFileNames . SheetRels ( sheetRelsXml . Key ) ;
85
+ _archive . Entries . SingleOrDefault ( s => s . FullName == sheetRelsXmlPath ) ? . Delete ( ) ;
86
+ await CreateZipEntryAsync ( sheetRelsXmlPath , null , ExcelXml . DefaultSheetRelXml . Replace ( "{{format}}" , sheetRelsXml . Value ) , cancellationToken ) ;
87
+ }
88
+
89
+ _archive . Entries . SingleOrDefault ( s => s . FullName == ExcelFileNames . Workbook ) ? . Delete ( ) ;
90
+ await CreateZipEntryAsync ( ExcelFileNames . Workbook , ExcelContentTypes . Workbook , ExcelXml . DefaultWorkbookXml . Replace ( "{{sheets}}" , workbookXml . ToString ( ) ) , cancellationToken ) ;
91
+
92
+ _archive . Entries . SingleOrDefault ( s => s . FullName == ExcelFileNames . WorkbookRels ) ? . Delete ( ) ;
93
+ await CreateZipEntryAsync ( ExcelFileNames . WorkbookRels , null , ExcelXml . DefaultWorkbookXmlRels . Replace ( "{{sheets}}" , workbookRelsXml . ToString ( ) ) , cancellationToken ) ;
94
+
95
+ _archive . Dispose ( ) ;
96
+ }
97
+
35
98
internal async Task GenerateDefaultOpenXmlAsync ( CancellationToken cancellationToken )
36
99
{
37
100
await CreateZipEntryAsync ( ExcelFileNames . Rels , ExcelContentTypes . Relationships , ExcelXml . DefaultRels , cancellationToken ) ;
@@ -589,7 +652,7 @@ private async Task WriteColumnsWidthsAsync(MiniExcelAsyncStreamWriter writer, IE
589
652
await writer. WriteAsync( WorksheetXml. EndCols) ;
590
653
}
591
654
592
- private static async Task PrintHeaderAsync( MiniExcelAsyncStreamWriter writer, List< ExcelColumnInfo> props)
655
+ private async Task PrintHeaderAsync( MiniExcelAsyncStreamWriter writer, List< ExcelColumnInfo> props)
593
656
{
594
657
var xIndex = 1 ;
595
658
var yIndex = 1 ;
@@ -658,9 +721,9 @@ private async Task<int> GenerateSheetByColumnInfoAsync<T>(MiniExcelAsyncStreamWr
658
721
return yIndex - 1 ;
659
722
}
660
723
661
- private static async Task WriteCellAsync( MiniExcelAsyncStreamWriter writer, string cellReference, string columnName)
724
+ private async Task WriteCellAsync( MiniExcelAsyncStreamWriter writer, string cellReference, string columnName)
662
725
{
663
- await writer. WriteAsync( WorksheetXml. Cell( cellReference, "str", "1 ", ExcelOpenXmlUtils. EncodeXML( columnName) ) ) ;
726
+ await writer. WriteAsync( WorksheetXml. Cell( cellReference, "str", GetCellXfId ( "1 ") , ExcelOpenXmlUtils. EncodeXML( columnName) ) ) ;
664
727
}
665
728
666
729
private async Task WriteCellAsync( MiniExcelAsyncStreamWriter writer, int rowIndex, int cellIndex, object value, ExcelColumnInfo p, ExcelWidthCollection widthCollection)
@@ -670,7 +733,7 @@ private async Task WriteCellAsync(MiniExcelAsyncStreamWriter writer, int rowInde
670
733
671
734
if ( _configuration. EnableWriteNullValueCell && valueIsNull)
672
735
{
673
- await writer. WriteAsync( WorksheetXml. EmptyCell( columnReference, "2 ") ) ;
736
+ await writer. WriteAsync( WorksheetXml. EmptyCell( columnReference, GetCellXfId ( "2 ") ) ) ;
674
737
return ;
675
738
}
676
739
@@ -697,7 +760,7 @@ private async Task WriteCellAsync(MiniExcelAsyncStreamWriter writer, int rowInde
697
760
}
698
761
}
699
762
700
- await writer. WriteAsync( WorksheetXml. Cell( columnReference, dataType, styleIndex, cellValue, preserveSpace: preserveSpace, columnType: columnType) ) ;
763
+ await writer. WriteAsync( WorksheetXml. Cell( columnReference, dataType, GetCellXfId ( styleIndex) , cellValue, preserveSpace: preserveSpace, columnType: columnType) ) ;
701
764
widthCollection? . AdjustWidth( cellIndex, cellValue) ;
702
765
}
703
766
@@ -727,41 +790,59 @@ private async Task AddFilesToZipAsync(CancellationToken cancellationToken)
727
790
/// </summary>
728
791
private async Task GenerateStylesXmlAsync( CancellationToken cancellationToken)
729
792
{
730
- var styleXml = GetStylesXml( _configuration. DynamicColumns) ;
731
-
732
- await CreateZipEntryAsync(
733
- ExcelFileNames. Styles,
734
- ExcelContentTypes. Styles,
735
- styleXml,
736
- cancellationToken) ;
793
+ using ( var context = new SheetStyleBuildContext( _zipDictionary, _archive, _utf8WithBom, _configuration. DynamicColumns) )
794
+ {
795
+ var builder = ( ISheetStyleBuilder) null ;
796
+ switch ( _configuration. TableStyles)
797
+ {
798
+ case TableStyles. None:
799
+ builder = new MinimalSheetStyleBuilder( context) ;
800
+ break ;
801
+ case TableStyles. Default:
802
+ builder = new DefaultSheetStyleBuilder( context) ;
803
+ break ;
804
+ }
805
+ var result = await builder. BuildAsync( cancellationToken) ;
806
+ cellXfIdMap = result. CellXfIdMap;
807
+ }
737
808
}
738
809
739
810
private async Task GenerateDrawinRelXmlAsync( CancellationToken cancellationToken)
740
811
{
741
812
for ( int sheetIndex = 0 ; sheetIndex < _sheets. Count; sheetIndex++ )
742
813
{
743
- var drawing = GetDrawingRelationshipXml( sheetIndex) ;
744
- await CreateZipEntryAsync(
745
- ExcelFileNames. DrawingRels( sheetIndex) ,
746
- string . Empty,
747
- ExcelXml. DefaultDrawingXmlRels. Replace( "{ { format} } ", drawing) ,
748
- cancellationToken) ;
814
+ await GenerateDrawinRelXmlAsync( sheetIndex, cancellationToken) ;
749
815
}
750
816
}
751
817
818
+ private async Task GenerateDrawinRelXmlAsync( int sheetIndex, CancellationToken cancellationToken)
819
+ {
820
+ var drawing = GetDrawingRelationshipXml( sheetIndex) ;
821
+ await CreateZipEntryAsync(
822
+ ExcelFileNames. DrawingRels( sheetIndex) ,
823
+ string . Empty,
824
+ ExcelXml. DefaultDrawingXmlRels. Replace( "{ { format} } ", drawing) ,
825
+ cancellationToken) ;
826
+ }
827
+
752
828
private async Task GenerateDrawingXmlAsync( CancellationToken cancellationToken)
753
829
{
754
830
for ( int sheetIndex = 0 ; sheetIndex < _sheets. Count; sheetIndex++ )
755
831
{
756
- var drawing = GetDrawingXml( sheetIndex) ;
757
- await CreateZipEntryAsync(
758
- ExcelFileNames. Drawing( sheetIndex) ,
759
- ExcelContentTypes. Drawing,
760
- ExcelXml. DefaultDrawing. Replace( "{ { format} } ", drawing) ,
761
- cancellationToken) ;
832
+ await GenerateDrawingXmlAsync( sheetIndex, cancellationToken) ;
762
833
}
763
834
}
764
835
836
+ private async Task GenerateDrawingXmlAsync( int sheetIndex, CancellationToken cancellationToken)
837
+ {
838
+ var drawing = GetDrawingXml( sheetIndex) ;
839
+ await CreateZipEntryAsync(
840
+ ExcelFileNames. Drawing( sheetIndex) ,
841
+ ExcelContentTypes. Drawing,
842
+ ExcelXml. DefaultDrawing. Replace( "{ { format} } ", drawing) ,
843
+ cancellationToken) ;
844
+ }
845
+
765
846
/// <summary>
766
847
/// workbook.xml 、 workbookRelsXml
767
848
/// </summary>
0 commit comments