2018-09-12 21:01:52 +01:00
// http://officeopenxml.com/WPtableGrid.php
2018-10-23 23:44:50 +01:00
import { XmlComponent } from "file/xml-components" ;
2019-11-24 01:22:17 +00:00
import { AlignmentType } from "../paragraph" ;
2017-09-19 15:49:27 +01:00
import { TableGrid } from "./grid" ;
2019-09-26 02:03:17 +01:00
import { TableCell , VerticalMergeType , WidthType } from "./table-cell" ;
2019-11-18 01:04:31 +00:00
import { ITableBordersOptions , ITableFloatOptions , TableProperties } from "./table-properties" ;
2019-06-25 20:57:46 +01:00
import { TableLayoutType } from "./table-properties/table-layout" ;
2018-10-23 23:44:50 +01:00
import { TableRow } from "./table-row" ;
2019-09-13 00:51:20 +01:00
2019-03-08 01:09:21 +00:00
/ *
0 - width columns don ' t get rendered correctly , so we need
to give them some value . A reasonable default would be
~ 6 in / n u m C o l s , b u t i f w e d o t h a t i t b e c o m e s v e r y h a r d
to resize the table using setWidth , unless the layout
algorithm is set to 'fixed' . Instead , the approach here
means even in 'auto' layout , setting a width on the
table will make it look reasonable , as the layout
algorithm will expand columns to fit its content
* /
2019-03-13 02:29:11 +00:00
export interface ITableOptions {
2019-09-13 00:51:20 +01:00
readonly rows : TableRow [ ] ;
2019-09-26 02:03:17 +01:00
readonly width ? : {
readonly size : number ;
readonly type ? : WidthType ;
} ;
2019-03-13 02:29:11 +00:00
readonly columnWidths? : number [ ] ;
2019-04-18 13:55:18 +10:00
readonly margins ? : {
readonly marginUnitType? : WidthType ;
2019-03-13 02:29:11 +00:00
readonly top? : number ;
readonly bottom? : number ;
readonly right? : number ;
readonly left? : number ;
} ;
readonly float? : ITableFloatOptions ;
2019-06-25 20:57:46 +01:00
readonly layout? : TableLayoutType ;
2019-11-18 01:04:31 +00:00
readonly borders? : ITableBordersOptions ;
2019-11-24 01:22:17 +00:00
readonly alignment? : AlignmentType ;
2019-03-13 02:29:11 +00:00
}
2017-09-19 15:49:27 +01:00
export class Table extends XmlComponent {
2018-01-29 01:55:25 +00:00
private readonly properties : TableProperties ;
2017-09-19 15:49:27 +01:00
2019-03-13 02:29:11 +00:00
constructor ( {
rows ,
2019-09-26 02:03:17 +01:00
width ,
2019-09-13 00:51:20 +01:00
columnWidths = Array < number > ( Math . max ( . . . rows . map ( ( row ) = > row . CellCount ) ) ) . fill ( 100 ) ,
2019-04-18 13:55:18 +10:00
margins : { marginUnitType , top , bottom , right , left } = { marginUnitType : WidthType.AUTO , top : 0 , bottom : 0 , right : 0 , left : 0 } ,
2019-03-13 02:29:11 +00:00
float ,
2019-06-25 20:57:46 +01:00
layout ,
2019-11-18 01:04:31 +00:00
borders ,
2019-11-24 01:22:17 +00:00
alignment ,
2019-03-13 02:29:11 +00:00
} : ITableOptions ) {
2017-09-19 15:49:27 +01:00
super ( "w:tbl" ) ;
this . properties = new TableProperties ( ) ;
this . root . push ( this . properties ) ;
2019-11-18 01:04:31 +00:00
if ( borders ) {
this . properties . setBorder ( borders ) ;
} else {
this . properties . setBorder ( { } ) ;
}
2019-09-26 02:03:17 +01:00
if ( width ) {
this . properties . setWidth ( width . size , width . type ) ;
} else {
this . properties . setWidth ( 100 ) ;
}
2019-04-18 13:55:18 +10:00
this . properties . CellMargin . addBottomMargin ( bottom || 0 , marginUnitType ) ;
this . properties . CellMargin . addTopMargin ( top || 0 , marginUnitType ) ;
this . properties . CellMargin . addLeftMargin ( left || 0 , marginUnitType ) ;
this . properties . CellMargin . addRightMargin ( right || 0 , marginUnitType ) ;
2017-09-19 15:49:27 +01:00
2019-09-13 00:51:20 +01:00
this . root . push ( new TableGrid ( columnWidths ) ) ;
2017-09-19 15:49:27 +01:00
2019-09-13 00:51:20 +01:00
for ( const row of rows ) {
this . root . push ( row ) ;
}
2019-03-13 02:29:11 +00:00
2020-06-20 19:47:46 +08:00
rows . forEach ( ( row , rowIndex ) = > {
row . cells . forEach ( ( cell , cellIndex ) = > {
2019-09-25 00:57:24 +01:00
// Row Span has to be added in this method and not the constructor because it needs to know information about the column which happens after Table Cell construction
// Row Span of 1 will crash word as it will add RESTART and not a corresponding CONTINUE
if ( cell . options . rowSpan && cell . options . rowSpan > 1 ) {
2020-06-22 12:25:51 +08:00
const columnIndex = row . rootIndexToColumnIndex ( cellIndex + 1 ) ;
const startRowIndex = rowIndex + 1 ;
2020-06-20 19:47:46 +08:00
const endRowIndex = rowIndex + ( cell . options . rowSpan - 1 ) ;
2020-06-22 12:25:51 +08:00
for ( let i = startRowIndex ; i <= endRowIndex ; i ++ ) {
rows [ i ] . addCellToColumnIndex (
2019-09-25 00:57:24 +01:00
new TableCell ( {
2020-06-20 21:36:35 +08:00
columnSpan : cell.options.columnSpan ,
2020-06-20 20:20:22 +08:00
borders : cell.options.borders ,
2019-09-25 00:57:24 +01:00
children : [ ] ,
2019-09-26 02:03:17 +01:00
verticalMerge : VerticalMergeType.CONTINUE ,
2019-09-25 00:57:24 +01:00
} ) ,
2020-06-22 12:25:51 +08:00
columnIndex ,
2019-09-25 00:57:24 +01:00
) ;
}
}
} ) ;
2020-06-20 19:47:46 +08:00
} ) ;
2019-09-25 00:57:24 +01:00
2019-03-13 02:29:11 +00:00
if ( float ) {
this . properties . setTableFloatProperties ( float ) ;
2017-09-19 15:49:27 +01:00
}
2019-06-25 20:57:46 +01:00
if ( layout ) {
this . properties . setLayout ( layout ) ;
}
2019-11-24 01:22:17 +00:00
if ( alignment ) {
this . properties . setAlignment ( alignment ) ;
}
2017-09-19 15:49:27 +01:00
}
}