1+ using System . Text ;
2+ using Syncfusion . DocIO ;
3+ using Syncfusion . DocIO . DLS ;
4+ using Syncfusion . XlsIO ;
5+
6+ class Program
7+ {
8+ static void Main ( string [ ] args )
9+ {
10+ // Load existing word document
11+ using ( FileStream inputfileStream = new FileStream ( Path . GetFullPath ( @"../../../Data/Input.docx" ) , FileMode . Open ) )
12+ {
13+ using ( WordDocument document = new WordDocument ( inputfileStream , FormatType . Automatic ) )
14+ {
15+ using ( ExcelEngine engine = new ExcelEngine ( ) )
16+ {
17+ IApplication app = engine . Excel ;
18+ app . DefaultVersion = ExcelVersion . Excel2016 ;
19+
20+ // Create one sheet to start with; we’ll add sheets as we find more tables.
21+ IWorkbook workbook = app . Workbooks . Create ( 1 ) ;
22+ int sheetIndex = 0 ;
23+ int tableNumber = 0 ;
24+
25+ // Get table entities in word document
26+ List < Entity > entities = document . FindAllItemsByProperty ( EntityType . Table , null , null ) ;
27+
28+ foreach ( Entity entity in entities )
29+ {
30+ WTable wTable = ( WTable ) entity ;
31+
32+ if ( sheetIndex >= workbook . Worksheets . Count )
33+ workbook . Worksheets . Create ( ) ;
34+
35+ IWorksheet worksheet = workbook . Worksheets [ sheetIndex ++ ] ;
36+ worksheet . Name = $ "Table{ ++ tableNumber } ";
37+
38+ // Export with merges starting at row=1, col=1
39+ ExportWordTableToExcelMerged ( wTable , worksheet , 1 , 1 ) ;
40+
41+ // Formatting
42+ worksheet . UsedRange . AutofitRows ( ) ;
43+ worksheet . UsedRange . AutofitColumns ( ) ;
44+ }
45+ using ( FileStream outputStream = new FileStream ( Path . GetFullPath ( @"../../../Output/Result.xlsx" ) , FileMode . Create ) )
46+ {
47+ workbook . SaveAs ( outputStream ) ;
48+ }
49+ workbook . Close ( ) ;
50+ }
51+ }
52+ }
53+ }
54+
55+ /// <summary>
56+ /// Writes a Word table to the worksheet, preserving horizontal and vertical merges.
57+ /// startRow/startCol are 1-based Excel coordinates where the table should be placed.
58+ /// </summary>
59+ private static void ExportWordTableToExcelMerged ( IWTable table , IWorksheet worksheet , int startRow , int startCol )
60+ {
61+ // Iterate table rows
62+ for ( int r = 0 ; r < table . Rows . Count ; r ++ )
63+ {
64+ WTableRow wRow = table . Rows [ r ] ;
65+
66+ // Map Word's logical grid to Excel columns using GridSpan
67+ int gridCol = startCol ;
68+
69+ for ( int i = 0 ; i < wRow . Cells . Count ; i ++ )
70+ {
71+ WTableCell wCell = wRow . Cells [ i ] ;
72+
73+ // Horizontal width in grid columns
74+ int hSpan = Math . Max ( 1 , ( int ) wCell . GridSpan ) ;
75+
76+ // Merge flags (DocIO)
77+ CellMerge vFlag = wCell . CellFormat . VerticalMerge ;
78+ CellMerge hFlag = wCell . CellFormat . HorizontalMerge ;
79+
80+ // Excel start cell for this Word cell
81+ int xRow = startRow + r ;
82+ int xCol = gridCol ;
83+
84+ // Compute vertical span when this cell is the START of a vertical merge
85+ int vSpan = 1 ;
86+ if ( vFlag == CellMerge . Start )
87+ {
88+ // Count how many subsequent rows continue the merge at the same grid column
89+ for ( int nr = r + 1 ; nr < table . Rows . Count ; nr ++ )
90+ {
91+ WTableRow nextRow = table . Rows [ nr ] ;
92+ WTableCell nextCell = GetCellAtGridColumn ( nextRow , ( xCol - startCol + 1 ) ) ;
93+ if ( nextCell != null && nextCell . CellFormat . VerticalMerge == CellMerge . Continue )
94+ vSpan ++ ;
95+ else
96+ break ;
97+ }
98+ }
99+
100+ // Is Start or None of a merge region
101+ bool isStartorNone =
102+ ( vFlag != CellMerge . Continue ) &&
103+ ( hFlag != CellMerge . Continue ) ;
104+
105+ if ( isStartorNone )
106+ {
107+ // To get the exact lest row and last column -1
108+ int lastRow = xRow + vSpan - 1 ;
109+ int lastCol = xCol + hSpan - 1 ;
110+
111+ // Merge in Excel if region spans multiple cells
112+ if ( lastRow > xRow || lastCol > xCol )
113+ worksheet . Range [ xRow , xCol , lastRow , lastCol ] . Merge ( ) ; // XlsIO merge
114+
115+ // Write the visible text to the top-left Excel cell
116+ IRange range = worksheet . Range [ xRow , xCol ] ;
117+ range . Text = BuildCellText ( wCell ) ;
118+
119+ // Text styling
120+ range . CellStyle . HorizontalAlignment = ExcelHAlign . HAlignCenter ;
121+ range . CellStyle . VerticalAlignment = ExcelVAlign . VAlignCenter ;
122+ // Border formatting
123+ worksheet . Range [ xRow , xCol , lastRow , lastCol ] . CellStyle . Borders [ ExcelBordersIndex . EdgeLeft ] . LineStyle = ExcelLineStyle . Thin ;
124+ worksheet . Range [ xRow , xCol , lastRow , lastCol ] . CellStyle . Borders [ ExcelBordersIndex . EdgeRight ] . LineStyle = ExcelLineStyle . Thin ;
125+ worksheet . Range [ xRow , xCol , lastRow , lastCol ] . CellStyle . Borders [ ExcelBordersIndex . EdgeTop ] . LineStyle = ExcelLineStyle . Thin ;
126+ worksheet . Range [ xRow , xCol , lastRow , lastCol ] . CellStyle . Borders [ ExcelBordersIndex . EdgeBottom ] . LineStyle = ExcelLineStyle . Thin ;
127+ }
128+ // Add Excel column cursor by the horizontal span of this Word cell
129+ gridCol += hSpan ;
130+ }
131+ }
132+ }
133+
134+ /// <summary>
135+ /// Returns the WTableCell occupying the given 1-based "grid column" in this row,
136+ /// taking each cell's GridSpan into account.
137+ /// </summary>
138+ static WTableCell GetCellAtGridColumn ( WTableRow row , int gridColumn )
139+ {
140+ int cursor = 1 ;
141+ foreach ( WTableCell c in row . Cells )
142+ {
143+ int span = Math . Max ( ( int ) 1 , ( int ) c . GridSpan ) ;
144+ int start = cursor ;
145+ int end = cursor + span - 1 ;
146+ if ( gridColumn >= start && gridColumn <= end )
147+ return c ;
148+ cursor += span ;
149+ }
150+ return null ;
151+ }
152+
153+ /// <summary>
154+ /// Concatenate all paragraph texts in a Word cell (one per line).
155+ /// </summary>
156+ static string BuildCellText ( WTableCell cell )
157+ {
158+ StringBuilder sb = new StringBuilder ( ) ;
159+ for ( int p = 0 ; p < cell . Paragraphs . Count ; p ++ )
160+ {
161+ WParagraph para = ( WParagraph ) cell . Paragraphs [ p ] ;
162+ string text = para . Text ? . TrimEnd ( ) ;
163+ if ( ! string . IsNullOrEmpty ( text ) )
164+ {
165+ if ( sb . Length > 0 ) sb . AppendLine ( ) ;
166+ sb . Append ( text ) ;
167+ }
168+ }
169+ return sb . ToString ( ) ;
170+ }
171+ }
0 commit comments