Type xlsxTable = Class
	///缺省构造函数
	Function Create(sheet, excel); overload;
	Begin
		excel_ := excel;
		sheetName_ := sheet;
		zipfile_ := excel.Zip();
	End;

	class Function NewObject(sheet, excel);
	Begin
		excel_ := excel;
		o := excel_.WorkBook().GetSheetObj(sheet);//sheet存在
		if not ifObj(o) then return 0;
		return new xlsxTable(sheet, excel);
	End;

	Function AddTable(topLeft, bottomRight, format, includeHeader);
	Begin
		[rid, table_id, table_name] := addTableXmlFileAndRelation();

		table := TOfficeObj('TExcelTable');
		table.Xmlns := 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';
		table.Mc := 'http://schemas.openxmlformats.org/markup-compatibility/2006';
		table.Ignorable := 'xr xr3';
		table.Xr := 'http://schemas.microsoft.com/office/spreadsheetml/2014/revision';
		table.Xr3 := 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision3';
		table.Id := table_id;
		table.Name := '表' $ table_id;
		table.DisplayName := class(xlsxTable).GenerateValidDisplayName(format.TableName, tableid);
		table.Ref := topLeft $ ':' $ bottomRight;
		table.HeaderRowCount := format.HeaderRowCount ? '1' : nil;
		table.TotalsRowShown := format.TotalsRowShown ? '1' : '0';
		table.AutoFilter := table.Ref;

		format.TableName := nil;
		format.HeaderRowCount := nil;
		format.TotalsRowShown := nil;

		// <tableColumns />
		[err1, col1, row1] := excel_.CellNameToCoordinates(topLeft);
		[err2, col2, row2] := excel_.CellNameToCoordinates(bottomRight);
		table_str := getTableColumnsXmlString(col1, col2, row1, includeHeader);

		table_xml := excel_.WorkBook().GetXmlFileObj(table_name);
		table_node := table_xml.FirstChild('table');
		marshal := table.Marshal();
		class(TSXml).UpdateNode(table_node, marshal['attributes'], marshal['children']);
		table_node.InsertEndChild(table_str);
		table_node.InsertEndChild(format.Marshal());

		//sheetN.xml
		sheet_xml := excel_.WorkBook().GetSheetXmlFile(sheetName_);
		worksheet_node := sheet_xml.FirstChildElement('worksheet');
		table_part := worksheet_node.FirstChildElement('tableParts');
		if not ifObj(table_part) then
		begin
			table_part := worksheet_node.InsertEndChild('element', 'tableParts');
			count := 1;
		end
		else begin
			count := strtoint(table_part.GetAttribute('count')) + 1;
		end
		node := table_part.InsertEndChild('element', 'tablePart');
		node.SetAttribute('r:id', 'rId' $ rid);
		table_part.SetAttribute('count', count);

	End

	class Function GenerateValidDisplayName(name, nameId);
	Begin
		if ifnil(name) then name := '表' $ nameId;
		if TOfficeApi().Get('Table-' $ name) then
		begin
			new_name := '表' $ nameId;
			while TOfficeApi().Get('Table-' $ new_name) do new_name := '表' $ ++nameId;
			TOfficeApi().Set('Table-' $ new_name, true);
			return new_name;
		end
		TOfficeApi().Set('Table-' $ name, true);
		return name;
	End

private
	Function getTableColumnsXmlString(begCol, endCol, row, includeHeader);
	Begin
		table_str := '<tableColumns count="' $ (endCol - begCol + 1) $ '">';
		id := 1;
		col_index := 1;
		if not includeHeader then excel_.WorkBook().InsertRow(sheetName_, row);
		for i:=begCol to endCol do
		begin
			[err, cell] := excel_.CoordinatesToCellName(i, row, false);
			if includeHeader then
			begin
				[err, name] := excel_.WorkBook().GetCellValue(sheetName_, cell);
				name := "列" $ col_index++;
				if err then excel_.WorkBook().SetCellValue(sheetName_, cell, name);
			end
			else begin
				name := "列" $ col_index++;
				excel_.WorkBook().SetCellValue(sheetName_, cell, name);
			end
			table_str += format('<tableColumn id="%d" name="%s" />', id, name);
		end
		table_str += "</tableColumns>";

		return table_str;
	End

	Function addTableXmlFileAndRelation();
	Begin
		sheet_rels_file := excel_.WorkBook().GetSheetRelsFile(sheetName_);
		[rid, target] := class(TSXml).FindRelationshipRid(sheet_rels_file, '');
		rid ++;
		table_id := excel_.WorkBook().GetFilesCount('xl/tables/') + 1;
		table_name := 'xl/tables/table' + inttostr(table_id) + '.xml';
		table_target := '../tables/table' + inttostr(table_id) + '.xml';
		excel_.zip().Add(table_name, class(TSXml).XmlHeader() + "<table />");
		class(TSXml).AddRelationshipRid(sheet_rels_file, table_target, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/table', 'rId' $ rid);
		content_xml := excel_.WorkBook().GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
		class(TSXml).AddOverrideContentType(content_xml, '/' + table_name, class(TSXml).GetTemplate('tableContentType'));

		return array(rid, table_id, table_name);
	End

private
	sheetName_:string; //sheet名称
	excel_;//TSExcelFile对象
	zipfile_;
	tableXmlFile_;
End;
