dev 1.0.1

This commit is contained in:
csh 2022-10-27 16:43:55 +08:00
parent d6939071b3
commit 2674ab8eb3
23 changed files with 8759 additions and 1 deletions

BIN
ExcelFile使用帮助.xlsx Normal file

Binary file not shown.

View File

@ -1,3 +1,15 @@
# OfficePlugin
TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
## 部署
### windows
- [fmt_pubkrnl_plugin](./Windows-X64/fmt_pubkrnl_plugin.dll) 放入 tsl 安装根目录下 Plugin 文件夹
- [office_plugin](./Windows-X64/office_plugin.dll) 放入 tsl 安装根目录下 Plugin 文件夹
- [tsxlsx.dll](./Windows-X64/tsxlsx.dll) 放入 tsl 安装根目录
## 帮助文档
- [Excel 帮助文档](./ExcelFile%E4%BD%BF%E7%94%A8%E5%B8%AE%E5%8A%A9.xlsx)

Binary file not shown.

Binary file not shown.

BIN
Windows-X64/tsxlsx.dll Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,882 @@
Type TSExcelFile = Class
///Version: V1.0 2022-08-08
///适用于 Microsoft Excel? 2007 及以上版本创建的电子表格文档。支持 XLSX / XLSM / XLTM / XLTX 等多种文档格式。
///纯TSL模块实现
///Excel文件读写接口
//缺省构造函数
Function Create(); overload;
Begin
init();
End;
//构造函数打开已经存在的excel文件
//alias: string文件目录别名
//fname: string文件名
Function Create(alias, fname); overload;
Begin
init();
OpenFile(alias, fname);
End;
//析构函数
Function Destory();
Begin
End;
//初始化
Function init();
Begin
zipfile_ := new ZipFile();
xml_ := new xlsxXml();
End;
///打开excel文件
///alias: string文件目录别名
///fname: string文件名
///返回:[err, errmsg]
Function OpenFile(alias, fname);
Begin
if not ifObj(zipfile_) then return array(-1, 'Create ZipFile object fail.');
[err, errmsg] := zipfile_.Open(alias, fname);
if err=0 then Begin
workbook_ := new xlsxWorkBook(zipfile_, xml_);
workbook_.Load();
End;
return array(err, errmsg);
End;
///新建excel文件
///返回:[err, info]
Function NewFile();
Begin
path := ExtractFileDir(ExtractFileDir(PluginPath()));
{$IFNDEF Win32}
defaultFileName := path + '\\funcext\\TSOffice\\default.xlsx';
{$ELSE}
defaultFileName := path + '/funcext/TSOffice/default.xlsx';
{$ENDIF}
[err, errinfo] := OpenFile('', defaultFileName);
if not err then return array(err, errinfo);
if not ifObj(zipfile_) then return array(-1, 'Create ZipFile object fail.');
zipfile_.Add(xml_.GetFileName('rels'), xml_.XmlHeader() + xml_.GetTemplate('rels'));
zipfile_.Add(xml_.GetFileName('docProps_app'), xml_.XmlHeader() + xml_.GetTemplate('docProps_app'));
zipfile_.Add(xml_.GetFileName('docProps_core'), xml_.XmlHeader() + xml_.GetTemplate('docProps_core'));
zipfile_.Add(xml_.GetFileName('workbook_rels'), xml_.XmlHeader() + xml_.GetTemplate('workbook_rels'));
zipfile_.Add(xml_.GetFileName('theme1'), xml_.XmlHeader() + xml_.GetTemplate('theme1'));
zipfile_.Add(xml_.GetFileName('sheet1'), xml_.XmlHeader() + xml_.GetTemplate('sheet1'));
zipfile_.Add(xml_.GetFileName('styles'), xml_.XmlHeader() + xml_.GetTemplate('styles'));
zipfile_.Add(xml_.GetFileName('workbook'), xml_.XmlHeader() + xml_.GetTemplate('workbook'));
zipfile_.Add(xml_.GetFileName('Content_Types'), xml_.XmlHeader() + xml_.GetTemplate('Content_Types'));
workbook_ := new xlsxWorkBook(zipfile_, xml_);
workbook_.Load();
return array(0, 'ok');
End;
///保存文件
///返回: [err, info]
Function Save();
Begin
return zipfile_.Save();
End;
///另存为
///alias: string文件目录别名
///fname: string文件名
///返回: [err, info]
Function SaveAs(alias, fname);
Begin
return zipfile_.Save(alias, fname);
End;
///真实文件名
///返回string
Function FileName();
Begin
return zipfile_.FileName();
End;
///获取工作表列表
///返回: arry('Sheet1','Sheet2')
Function GetSheets();
Begin
return workbook_.GetSheets();
End;
///获取工作表数
///返回: integer
Function GetSheetsCount();
Begin
return workbook_.GetSheetsCount();
End;
///获取工作表名
///index: int工作表索引
///返回: [err, sheetname:string]
Function GetSheetName(index);
Begin
return workbook_.GetSheets()[index];
End;
///设置工作表名
///sourceName: string, 原工作表名
///destName: string目标工作表名
///返回:[err, errinfo]
Function SetSheetName(sourceName, destName);
Begin
return workbook_.SetSheetName(sourceName, destName);
End;
///创建新sheet
///sheet: string工作表名称
///返回: [err, info]
Function NewSheet(sheet);
Begin
return workbook_.NewSheet(sheet);
End;
///删除sheet
///sheet: string工作表名称
///返回: [err, info]
Function DeleteSheet(sheet);
Begin
return workbook_.DeleteSheet(sheet);
End;
///获取总列数
///sheet: string工作表名称
///返回: [err, TotalCols:int]
Function TotalCols(sheet);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return array(0, o.TotalCols());
return array(-1, '');
End;
///获取总行数
///sheet: string工作表名称
///返回: [err, TotalRows:int]
Function TotalRows(sheet);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return array(0, o.TotalRows());
return array(-1, '');
End;
///获取单元格的值
///sheet: string工作表名称
///axis: string单元格坐标如: "A6"
///返回: [err, value:string]
Function GetCellValue(sheet, axis);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return o.GetCellValue(axis);
return array(-1, '');
End;
///设置单元格的值
///sheet: string工作表名称
///axis: string单元格坐标如: "A6"
///val: Var可以是整数、字符串、数值型等nil 不设置值(可以调用ClearCell方法清空单元格),只设置属性
///[opt:Tany]可选参数单元格属性可以是xml字符串或天软数组
/// xml串opt := '<c t="s" s="1"></c>';
/// 数组: opt := array('t':'s', 's':'1');
/// 属性t单元格数据类型不设置的话数据类型为val的数据类型
/// t ->'s' 共享字符串、'b' bool 类型、'e' 错误类型、'inlineStr' 内联字符串类型、nil 数字类型、'str' 公式类型)
/// 属性s单元格样式
///返回: [err, info]
Function SetCellValue(sheet, axis, val, opt);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return array(0, o.SetCellValue(axis, val, opt));
return array(-1, '');
End;
///获取富文本格式
///sheet: string工作表名称
///axis: string单元格如"A7"
///返回: [err, richtxt:string]参见SetCellRichText
Function GetCellRichText(sheet, axis);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return o.GetCellValue(axis, 'RichText');
return array(-1, '');
End;
///设置富文本格式
///sheet: string工作表名称
///axis: string单元格如"A7"
///richtext: stringxml串或富文本对象TSOffice('TRichText')
///返回: [err, info]
Function SetCellRichText(sheet, axis, richtext);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then Begin
if ifObj(richtext) then
richtext := class(xlsxXml).Dom2Xml(richtext.Marshal());
return array(0, o.SetCellValue(axis, richtext, array('t':'s'), 'RichText'));
End;
return array(-1, 'The Sheet is not exist.');
End;
///清空单元格
///sheet: string工作表名称
///[TopLeft: string],左上角坐标,可选参数
///[BottomRight: string],右下角坐标,可选参数,
/// 用法1ClearCell(); //Clear整个sheet
/// 用法2ClearCell('A2'); //Clear 'A2'单元格
/// 用法3ClearCell('A5', 'D8'); //Clear矩形区间所有单元格
///返回: [err, info]
Function ClearCell(sheet, TopLeft, BottomRight);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return array(0, o.ClearCell(TopLeft, BottomRight));
return array(-1, '');
End;
///设置公式
///sheet: string工作表名称
///axis: string单元格如"A7"
///formula: string公式
///返回: [err, info]
Function SetCellFormula(sheet, axis, formula);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return o.SetCellFormula(axis, formula);
return array(-1, '');
End;
///获取公式
///sheet: string工作表名称
///axis: string单元格如"A7"
///返回: [err, formula:string]
Function GetCellFormula(sheet, axis);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return o.GetCellFormula(axis);
return array(-1, '');
End;
///按行赋值
///sheet: string工作表名称
///axis: string起始坐标如: "A4"
///slice: array()一维数组array(1,2,3,2,1,"hello")
///返回: [err, info]
Function SetSheetRow(sheet, axis, slice);
Begin
[err, col, row] := CellNameToCoordinates(axis);
if err then
return array(err, col);
for i:=0 to length(slice)-1 do Begin
[err, cell] := CoordinatesToCellName(col + i, row);
//println('{}->{}',cell,slice[i]);
SetCellValue(sheet, cell, slice[i]);
End;
return array(0, 'ok');
End;
///插入数据表
///sheet: string工作表名称
///axis: string左上角坐标如: "A4"
///data: table数据表
///[IncludeHeader: bool] 是否包括表头默认FALSE
///[IncludeIndex: bool] 是否自动添加索引号默认FALSE
///返回: [err, info]
Function InsertTable(sheet, axis, data, IncludeHeader, IncludeIndex);
Begin
if not ifarray(data) or length(data)=0 then
return array(-1, "Invalid Data.");
if FieldCount(data)=0 then Begin //数据是一维数组
return SetSheetRow(sheet, axis, data);
End;
[err, colNum, rowNum] := CellNameToCoordinates(axis);
if err then
return array(err, colNum);
if IncludeHeader then Begin
fields := FieldNames(data);
if IncludeIndex then Begin
fields := array("Index") union fields;
End;
[err, info] := SetSheetRow(sheet, axis, fields);
if err then
return array(err, info);
rowNum ++;
End;
if IncludeIndex then Begin
for i:=0 to length(data)-1 do Begin
[err, cell] := CoordinatesToCellName(colNum, rowNum + i);
if err then
return array(err, cell);
SetCellValue(sheet, cell, i+1);
End;
colNum ++;
End;
for i:=0 to length(data)-1 do Begin
[err, cell] := CoordinatesToCellName(colNum, rowNum + i);
if err then
return array(err, cell);
t := sselect * from data where thisrowindex = i End;
//PrintLn("cell={},data={}->{}",cell, data[i],t);
[err, info] := SetSheetRow(sheet, cell, t);
if err then
return array(err, info);
End;
return array(0, "OK");
End;
///读取数据表
///sheet: string工作表名称
///TopLeft: string左上角坐标如: "A4"
///BottomRight: string右下角坐标如: "B8"为空获取从TopLeft开始的整张表
///返回: [err, data:table]
Function GetTable(sheet, TopLeft, BottomRight);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return array(0, o.Import(TopLeft, BottomRight));
return array(-1, '');
End;
///插入列,在指定列前插入空白列
///sheet: string工作表名称
///col: string 列名,如: "D"
///返回: [err, info]
Function InsertCol(sheet, col);
Begin
return workbook_.InsertCol(sheet, col);
End;
///插入行,在指定列前插入空白行
///sheet: string工作表名称
///row: int
///返回: [err, info]
Function InsertRow(sheet, row);
Begin
return workbook_.InsertRow(sheet, row);
End;
///删除列
///sheet: string工作表名称
///col: string如: "D"
///返回: [err, info]
Function RemoveCol(sheet, col);
Begin
return workbook_.RemoveCol(sheet, col);
End;
///删除行
///sheet: string工作表名称
///row: int
///返回: [err, info]
Function RemoveRow(sheet, row);
Begin
return workbook_.RemoveRow(sheet, row);
End;
///设置行高度
///sheet: string工作表
///row: int
///height: double
///返回: [err, info]
Function SetRowHeight(sheet, row, height);
Begin
return workbook_.SetRowHeight(sheet, row, height);
End;
///获取行高度
///sheet: string工作表
///row: int
///返回: [err, info]
Function GetRowHeight(sheet, row);
Begin
return workbook_.GetRowHeight(sheet, row);
End;
///设置列宽度
///sheet: string工作表
///startcol: string开始列如: "A"
///endcol: string结束列如: "D"
///width: double
///返回: [err, info]
Function SetColWidth(sheet, startCol, endCol, width);
Begin
return workbook_.SetColWidth(sheet, startCol, endCol, width);
End;
///获取列宽度
///sheet: string工作表
///col: int
///返回: [err, info]
Function GetColWidth(sheet, col);
Begin
return workbook_.GetColWidth(sheet, col);
End;
///设置工作表默认列宽
///sheet: string工作表
///widthdouble
///返回: [err, info]
Function SetSheetDefaultColWidth(sheet, width);
Begin
return workbook_.SetSheetDefaultColWidth(sheet, width);
End
///获取工作表默认列宽
///sheet: string工作表
///返回: [err, width]
Function GetSheetDefaultColWidth(sheet);
Begin
return workbook_.GetSheetDefaultColWidth(sheet);
End
///添加批注
///sheet: string工作表名称
///axis: string单元格如"A7"
///Author:string
///comment: string
///返回: [err, info]
Function AddComment(sheet, axis, Author, comment);
Begin
o := getOj(sheet, 'xlsxComment');
if not ifObj(o) then return array(1, 'The sheet is not exist.');
return o.AddComment(axis, Author, comment);
End;
///添加图表
///sheet: string工作表名称
///range:string图表所处矩形区域"A5:F10"
///chart:TChart对象
///返回: [err, info]
Function AddChart(sheet, range, chart);
Begin
o := getOj(sheet, 'xlsxChart');
if not ifObj(o) then return array(1, 'The sheet is not exist.');
if not ifObj(chart) then return array(2, 'Invalid chart param.');
return o.AddChart(range, chart);
End;
///获取图表列表
///sheet: string工作表名称
///返回: [err, ChartList]
Function GetCharts(sheet);
Begin
return workbook_.GetCharts(sheet);
End;
///单元格坐标切分
///cell: string单元格坐标
///返回: [err, col:string, row:int]"AK47" -> return array(0, "AK", 47);
Function SplitCellName(cell);
Begin
return xlsx_call("SplitCellName", cell);
End;
///单元格坐标组合
///col: string
///row: int
///返回 [err, cell:string]参见SplitCellName
Function JoinCellName(col, row);
Begin
return xlsx_call("JoinCellName", col, row);
End;
///列名转索引
///name: string
///返回 [err, index:int]"AK" -> return array(0, 37);
Function ColumnNameToNumber(name);
Begin
return xlsx_call("ColumnNameToNumber", name);
End;
///索引转列名
///index: int
///返回 [err, name:string]37 -> return array(0, "AK");
Function ColumnNumberToName(index);
Begin
return xlsx_call("ColumnNumberToName", index);
End;
///单元格坐标转索引
///cell: string
///返回 [err, col:int, row: int] "A2" -> [1,2]
Function CellNameToCoordinates(cell);
Begin
return xlsx_call("CellNameToCoordinates", cell);
End;
///索引转单元格坐标
///col: int
///row: int
///abs: bool ,true返回"$A$1"格式false返回"A1"格式
///返回 [err, cell:string] [1,2,true] -> "$A$2"
Function CoordinatesToCellName(col, row, abs);
Begin
return xlsx_call("CoordinatesToCellName", col, row, abs);
End;
///RGB与HSL色彩空间色值转换
///r: int
///g: int
///b: int
///返回: [err, h:double, s:double, l:double]
Function RGBToHSL(r, g, b);
Begin
return xlsx_call("RGBToHSL", r, g, b);
End;
///HSL与RGB色彩空间色值转换
///h: double
///s: double
///l: double
///返回: [err, r:int, g:int, b:int]
Function HSLToRGB(sheet, h, s, l);
Begin
return xlsx_call("HSLToRGB", h, s, l);
End;
///新建样式对象
///style: TStyle对象
///返回: styleid
Function NewStyle(style);
Begin
styleObj := new xlsxStyles('', self);
return array(0, styleObj.GetStyleId(style));
End
///设置单元格样式
///sheet: string工作表名称
///TopLeft: string左上角坐标
///BottomRight: string右下角坐标
///styleid: string样式Id
///返回: [err, info]
Function SetCellStyle(sheet, TopLeft, BottomRight, styleid);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return array(0, o.SetCellStyle(TopLeft, BottomRight, styleid));
return array(-1, '');
End;
///获取单元格样式Id获取到的Id可以在复制单元格样式时作为调用 SetCellValue、或SetCellStyle 函数的参数使用。
///sheet: string工作表名称
///axis: string单元格如"A7"
///返回: [err, datastyle: int]
Function GetCellStyle(sheet, axis);
Begin
o := workbook_.GetSheetObj(sheet);
if ifObj(o) then return array(0, o.GetCellStyle(axis));
return array(-1, 'The sheet is not exist.');
End;
///设置工作表页眉页脚
///sheetstring工作表名称
///headerFooter: xlsxHeaderFooter对象
///返回:[err, info]
Function SetSheetHeaderFooter(sheet, headerFooter);
Begin
o := getOj(sheet, 'xlsxHeaderFooter');
if not ifObj(o) then return array(0, 'HeaderFooter对象不存在');
o.SetHeaderFooter(headerFooter);
return array(1, '');
End
///设置工作表可见性
///sheet: string, 工作表名称
///visible: bool
///返回:[err, info]
Function SetSheetVisible(sheet, visible);
Begin
return workbook_.SetSheetVisible(sheet, visible);
End
///获取工作表可见性
///sheet: string工作表名称
///返回: [err, visibility: bool]
Function GetSheetVisible(sheet);
Begin
return workbook_.GetSheetVisible(sheet);
End;
///设置行可见性
///sheet: string工作表
///row: int
///visible: bool
///返回: [err, info]
Function SetRowVisible(sheet, row, visible)
Begin
return workbook_.SetRowVisible(sheet, row, visible);
End
///获取工作表行可见性
///sheet: string工作表名称
///row: int, 行
///返回: [err, visible:int]
Function GetRowVisble(sheet, row);
Begin
return workbook_.GetRowVisble(sheet, row);
End
///设置列可见性
///sheet: string工作表
///col: string'A'
///visible: bool
///返回: [err, info]
Function SetColVisible(sheet, col, visible)
Begin
[err, col] := ColumnNameToNumber(col);
if err then return array(-1, col);
return workbook_.SetColVisible(sheet, col, visible);
End
///获取工作表列可见性
///sheet: string工作表名称
///col: string
///返回: [err, visible:int]
Function GetColVisble(sheet, col);
Begin
[err, col] := ColumnNameToNumber(col);
if err then return array(-1, col);
return workbook_.GetColVisble(sheet, col);
End
///设置工作表页边距
///sheet: string工作表名称
///margins: TMargins 对象
///返回: [err, info]
Function SetPageMargins(sheet, margins);
Begin
o := getOj(sheet, 'xlsxMargins');
if not ifObj(o) then return array(0, 'The sheet is not exist');
o.SetPageMargins(margins);
return array(0, '');
End;
///获取工作表页边距
///sheet: string工作表名称
///返回: [err, info]
///无错误时返回TMargins对象
Function GetPageMargins(sheet);
Begin
o := getOj(sheet, 'xlsxMargins');
if not ifObj(o) then return array(0, 'The sheet is not exist');
return o.GetPageMargins();
End;
///合并单元格
///sheet: string工作表名称
///hcell: string左上角坐标
///vcell: string右下角坐标
///返回: [err, info]
Function MergeCell(sheet, hcell, vcell);
Begin
return workbook_.MergeCell(sheet, hcell, vcell);
End;
///取消合并单元格
///sheet: string工作表名称
///hcell: string左上角坐标
///vcell: string右下角坐标
///返回: [err, info]
Function UnMergeCell(sheet, hcell, vcell);
Begin
return workbook_.UnMergeCell(sheet, hcell, vcell);
End;
///设置工作表视图属性
///sheet: string工作表名称
///viewIndex: int视图索引
///sheet: objectTSheetView对象
///返回: [err, info]
Function SetSheetViewOptions(sheet, viewIndex, sheetView);
Begin
o := getOj(sheet, 'xlsxSheetView');
if not ifObj(o) then return array(1, 'The sheet is not exist');
return o.SetSheetViewOptions(viewIndex, sheetView);
End;
///获取工作表视图属性
///sheet: string工作表名称
///viewindex: int视图索引viewIndex 可以是负数,如果是这样,则向后计数(-1 代表最后一个视图)
///返回: [err, SheetView]
Function GetSheetViewOptions(sheet, viewIndex);
Begin
o := getOj(sheet, 'xlsxSheetView');
if not ifObj(o) then return array(0, 'The sheet is not exist');
return o.GetSheetViewOptions(viewIndex);
End;
///设置工作表页面布局
///sheet: string工作表名称
///pageLayout: pageLayout对象属性:
/// BlackAndWhite bool //BlackAndWhite specified print black and white.
/// FirstPageNumber int //FirstPageNumber specified the first printed page number. If no value is specified, then 'automatic' is assumed.
/// PageLayoutOrientation string //PageLayoutOrientation defines the orientation of page layout for a worksheet.
/// PageLayoutPaperSize int //PageLayoutPaperSize defines the paper size of the worksheet.
/// FitToHeight int //FitToHeight specified the number of vertical pages to fit on.
/// FitToWidth int //FitToWidth specified the number of horizontal pages to fit on.
/// PageLayoutScale int //PageLayoutScale defines the print scaling. This attribute is restricted to values ranging from 10 (10%) to 400 (400%). This setting is overridden when fitToWidth and/or fitToHeight are in use.
///返回: [err, info]
Function SetPageLayout(sheet, pageLayout);
Begin
o := getOj(sheet, 'xlsxPageLayout');
if not ifObj(o) then return array(1, 'The sheet is not exist');
return o.SetPageLayout(sheet, pageLayout);
End;
///获取工作表页面布局
///sheet: string工作表名称
///返回: [err, option:pageLayout对象]
Function GetPageLayout(sheet);
Begin
o := getOj(sheet, 'xlsxPageLayout');
if not ifObj(o) then return array(1, 'The sheet is not exist');
return o.GetPageLayout();
End;
///设置工作簿应用程序属性
///appProps: TAppProperty对象属性:
/// Application string
/// ScaleCrop bool
/// DocSecurity int
/// Company string
/// LinksUpToDate bool
/// HyperlinksChanged bool
/// AppVersion string
///返回: [err, info]
Function SetAppProps(appProps);
Begin
o := getOj('', 'xlsxAppProperty');
if not ifObj(o) then return array(1, 'AppProperty error!');
return o.SetAppProps(appProps);
End;
///获取应用程序属性
///返回: [err, props:TAppProperty对象]
Function GetAppProps();
Begin
o := getOj('', 'xlsxAppProperty');
if not ifObj(o) then return array(1, 'AppProperty error!');
return o.GetAppProps();
End;
///sheet: string工作表名称
///返回: [err, info]
Function SetDefaultSheet(sheet);
Begin
return workbook_.SetDefaultSheet(sheet);
End
///返回:[err, sheet]
Function GetDefaultSheet();
Begin
return workbook_.GetDefaultSheet();
End
///设置工作表背景图片
///pictrue: 图片对象
///返回: [err, info]
Function SetSheetBackground(sheet, pictrue);
Begin
o := getOj(sheet, 'xlsxImage');
if not ifObj(o) then return array(1, 'The sheet is not exist.');
return o.SetSheetBackground(sheet);
End;
///设置超链接
///sheet: string工作表名称
///axis: string单元格如"A7"
///hyplinkTHyperLink对象
///返回: [err, info]
Function SetCellHyperLink(sheet, axis, hyperlink);
Begin
o := getOj(sheet, 'xlsxHyperLink');
if not ifObj(o) then return array(1, 'The sheet is not exist.');
return o.SetCellHyperLink(axis, hyperlink);
End;
///获取超链接
///sheet: string工作表名称
///axis: string单元格如"A7"
///返回: [err, hyperlink: THyperLink对象]
Function GetCellHyperLink(sheet, axis);
Begin
o := getOj(sheet, 'xlsxHyperLink');
if not ifObj(o) then return array(1, 'The sheet is not exist.');
return o.GetCellHyperLink(axis);
End;
Function WorkBook();
Begin
return workbook_;
End;
Function XmlObj();
Begin
return xml_;
End;
Function Zip();
Begin
return zipfile_;
End;
private
Function getOj(sheetname, objname);
Begin
if not ifarray(objMgr_) then objMgr_:= array();
k := sheetname + '.' + objname;
o := objMgr_[ k ];
if not ifnil(o) then return o;
case objname of
'xlsxMargin':
o := class(xlsxMargin).NewObject(sheetname, self);
'xlsxComment':
o := class(xlsxComment).NewObject(sheetname, self);
'xlsxStyles':
o := class(xlsxStyles).NewObject(sheetname, self);
'xlsxChart':
return class(xlsxChart).NewObject(sheetname, self);//不缓存xlsxChart对象
'xlsxHeaderFooter':
o := class(xlsxHeaderFooter).NewObject(sheetname, self);
'xlsxMargins':
o := class(xlsxMargins).NewObject(sheetname, self);
'xlsxSheetView':
o := class(xlsxSheetView).NewObject(sheetname, self);
'xlsxPageLayout':
o := class(xlsxPageLayout).NewObject(sheetname, self);
'xlsxAppProperty':
return class(xlsxAppProperty).NewObject(self);
'xlsxImage':
o := class(xlsxImage).NewObject(sheetname, self);
'xlsxHyperLink':
o := class(xlsxHyperLink).NewObject(sheetname, self);
End;
if ifObj(o) then objMgr_[k] := o;
return o;
End;
{
TODO// 需要移除,待完成
///设置工作表默认行高
///sheet: string工作表
///heightdouble
///返回: [err, info]
Function SetSheetDefaultRowHeight(sheet, height);
Begin
return workbook_.SetSheetDefaultRowHeight(sheet, height);
End
///获取工作表默认行高
///sheet: string工作表
///返回: [err, height]
Function GetSheetDefaultRowHeight(sheet);
Begin
return workbook_.GetSheetDefaultRowHeight(sheet);
End
}
zipfile_; //压缩文件对象
workbook_; //WorkBook对象
xml_; //xlsxXml对象
objMgr_; //各种对象缓存、管理
End;

View File

@ -0,0 +1,136 @@
Type NodeInfo = class
public
Function Create(name);
Begin
NodeName := name;
ExtAttr := array();
ExtNodes := array();
End
Function GetAttrs(); virtual;
Begin
return ExtAttr;
End
Function GetChildren(); virtual;
Begin
return ExtNodes;
End
Function GetNode(index); // 返回的index的对象
Begin
return ExtNodes[index]['obj'];
End
Function GetCount(); // 返回当前节点的个数
Begin
return length(ExtAttr);
End
// arr := array('sz': 15, 'style': 'line');
Function AddAttr(arr); // 添加属性
Begin
if not istable(arr) then return;
ExtAttr union= arr;
return 1;
End
Function Marshal();
Begin
children := getChildrenEx();
child_arr := array();
len := 0;
for i:=0 to length(children)-1 do
begin
node_type := children[i]['nodeType'];
obj := children[i]['obj'];
if ifnil(obj) then continue;
find := select thisrowindex as "rowindex_", * from child_arr where ['name'] = children[i]['name'] end;
if not ifnil(obj) and not ifObj(obj) and istable(find) and ifstring(children[i]['attrEx']) and children[i]['attrEx'] <> '' then
begin
if not ifarray(find[0]['attributes']) then find[0]['attributes'] := array();
key := children[i]['attrEx'];
find[0]['attributes'] union= array(key : obj);
child_arr[find[0]['rowindex_']]['attributes'] := find[0]['attributes'];
continue;
end
arr := array('type': 'element', 'name': children[i]['name'], 'attributes': array());
if node_type = 'empty' then // <b/>
begin
// child_arr[len] := arr;
// ++len;
// continue;
end
else if node_type = 'pcdata' then
begin
arr['children'] := array(('type': 'pcdata', 'value': obj));
end
else if ifObj(obj) then
begin
marshal := obj.Marshal();
if length(marshal['children'])=0 and length(marshal['attributes'])=0 then continue;
arr['children'] := marshal['children'];
arr['attributes'] union= marshal['attributes'];
end
else
begin
key := children[i]['attrName'] ? children[i]['attrName'] : children[i]['attrEx'] ? children[i]['attrEx'] : 'val';
arr['attributes'] := array(key : obj);
end
child_arr[len++] := arr;
end
name_arr := str2array(NodeName, '/');
tmp_arr := array('type': 'element', 'name': name_arr[length(name_arr)-1], 'children': child_arr);
for i:=length(name_arr)-2 downto 0 do
begin
tmp_arr := array('type': 'element', 'name': name_arr[i], 'children': array(tmp_arr));
end
attrs_arr := GetAttrs();
valid_arr := array();
for k, v in attrs_arr do
begin
if not ifnil(v) then valid_arr[k] := v;
end
tmp_arr['attributes'] := valid_arr;
return tmp_arr;
End
Function NewChildNode(nodeArr);
Begin
if not ifarray(nodeArr) then return 0;
if not ifstring(nodeArr['name']) then return 0;
arr := array(
'name': nodeArr['name'],
'obj': nodeArr['obj'],
'attrEx': nodeArr['attrEx'],
'nodeType': nodeArr['nodeType'],
);
ExtNodes union= arr;
return 1;
End
private
Function getChildrenEx();
Begin
r := GetChildren();
a := array();
for i:=0 to length(r)-1 do Begin
if ifarray(r[i]['obj']) then Begin
a union= r[i]['obj'];
End
else
a[ length(a) ] := r[i];
end;
return a;
End;
public
NodeName;
ExtAttr;
ExtNodes;
End

View File

@ -0,0 +1,219 @@
Type TSImage = Class
Function Create(stream); overload;
Begin
content_ := stream;
imageDef := array(('Png', 0, (0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a)),
('Jfif',6,'JFIF'),
('Exif',6,'Exif'),
('Gif',0,'GIF87a'),
('Gif',0,'GIF89a'),
('Tiff',0,('M','M',0x00,'*')),
('Tiff',0,('I', 'I', '*', 0x00)),
('Bmp',0,'BM'));
ind := getImageDef(stream, imageDef);
if ind >= 0 then Begin
case imageDef[ind][0] of
'Gif':
[px_width, px_height, horz_dpi, vert_dpi] := gif_dimensions(stream);
'Bmp':
[px_width, px_height, horz_dpi, vert_dpi] := bmp_dimensions(stream);
'Tiff':
[px_width, px_height, horz_dpi, vert_dpi] := tiff_dimensions(stream, imageDef[ind][2]);
End;
End;
println('width={},height={}',px_width, px_height);
end;
Function Width();
Begin
return integer((px_width / horz_dpi) * 914400);
End;
Function Height();
Begin
return integer((px_height / vert_dpi) * 914400);
End;
(*
Function exif_dimensions(stream, r);
Begin
start := 0;
code := nil;
while code <> 0xd9 do Begin
[code, off] := _exif_next(start);
case code of
0xe0:
Begin
segment_length := _read_int(stream, off, '', 2);
density_units := _read_int(stream, off + 9, '', 1);
horz_dpi := read_int(stream, off + 10, '', 2);
vert_dpi := read_int(stream, off + 12, '', 2);
End;
End;
start := off + segment_length;
End;
End;
Function _exif_next(start);
Begin
while 1 do Begin
position := _offset_of_next_ff_byte(start);
[position, byte_] = _next_non_ff_byte(position+1);
start := position + 1;
if byte_ = 0x00 then continue;
marker_code := byte_;
segment_offset := position + 1;
break;
End;
return array(marker_code, segment_offset);
End;
Function _offset_of_next_ff_byte(start);
Begin
for i:=start to length(content_)-1 do Begin
byte_ := ord(content_[i]);
if byte_ <> 0xff then return array(start - 1, byte_);
return array(start, 0);
End;
Function _next_non_ff_byte(start);
Begin
for i:=start to length(content_)-1 do Begin
byte_ := ord(content_[i]);
if byte_ = 0xff then return start - 1;
return start;
End;
*)
Function tiff_dimensions(stream, r);
Begin
off := _read_int(stream, 4, r[0], 4);
count := _read_int(stream, off, r[0], 2);
m := array();
for i:=0 to count-1 do Begin
dir_entry_offset := off + 2 + i*12;
tag_code := _read_int(stream, dir_entry_offset, r[0], 2);
field_type := _read_int(stream, dir_entry_offset + 2, r[0], 2);
value_count := _read_int(stream, dir_entry_offset + 4, r[0], 4);
value_offset := _read_int(stream, dir_entry_offset + 8, r[0], 4);
case field_type of
2:
val := stream[value_offset:value_offset+value_count-1];
3:
if value_count=1 then
val := _read_int(stream, dir_entry_offset + 8, r[0], 2);
4:
if value_count=1 then
val := _read_int(stream, dir_entry_offset + 8, r[0], 4);
5:
if value_count=1 then Begin
numerator := _read_int(stream, value_offset, r[0], 4);
denominator := _read_int(stream, value_offset + 4, r[0], 4);
val := numerator / denominator;
End;
End;
println('off={}, tag={},type={},value_count={},value_off={},val={}',off, tag_code,field_type,value_count,value_offset,val);
m[tag_code] := val;
End;
px_width := m[256];
px_height := m[257];
horz_dpi := _tiff_dpi(282, m);
vert_dpi := _tiff_dpi(283, m);
return array(px_width, px_height, horz_dpi, vert_dpi);
End;
Function _read_int(stream, off, t, size);
Begin
stm := new TMemoryStream();
if t = 'M' then Begin
s := '';
setlength(s, 8);
for i:=0 to size-1 do Begin
s[i] := stream[off + size - i - 1];
End;
stm.Write(s, size);
End
else Begin
stm.Write(stream[off:off + 7], size);
End;
stm.Seek(0);
v := 0;
stm.Read(v, size);
return v;
End;
Function bmp_dimensions(stream);
Begin
s := new TMemoryStream();
s.Write(stream[0:63], 64);
s.Seek(0x12);
px_width := 0;
s.Read(px_width, 4);
px_height := 0;
s.Read(px_height, 4);
s.Seek(0x26);
horz_px_per_meter := 0;
s.Read(horz_px_per_meter, 4);
vert_px_per_meter := 0;
s.Read(vert_px_per_meter, 4);
horz_dpi := _bmp_dpi(horz_px_per_meter);
vert_dpi := _bmp_dpi(vert_px_per_meter);
return array(px_width, px_height, horz_dpi, vert_dpi);
End;
Function gif_dimensions(stream);
Begin
s := new TMemoryStream();
s.Write(stream[6:9], 4);
s.Seek(0);
px_width := 0;
s.Read(px_width, 2);
px_height := 0;
s.Read(px_height, 2);
return array(px_width, px_height, 72, 72);
End;
Function getImageDef(stream, imageDef);
Begin
for i:=0 to length(imageDef)-1 do Begin
off := imageDef[i][1];
len := length(imageDef[i][2]);
buf := stream[off:off+len-1];
if eq(buf, imageDef[i][2]) then Begin
return i;
End;
End;
return -1;
End;
Function eq(buf, r);
Begin
for i:=0 to length(buf)-1 do Begin
c := ifstring(r) ? r[i + 1] : r[i];
if ifint(c) then c := chr(c);
if c <> buf[i+1] then return 0;
End;
return 1;
End;
Function _tiff_dpi(tag, m);
Begin
if not ifint(m[tag]) then return 72;
v := ifint(m[296]) ? m[296] : 2;
if v = 1 then return 72;
units_per_inch := (v=2 ? 2.54 : 1);
dots_per_unit := m[tag];
return integer(round(dots_per_unit * units_per_inch));
End;
Function _bmp_dpi(px_per_meter);
Begin
if px_per_meter = 0 then return 96;
return integer(round(px_per_meter * 0.0254));
End;
Name;
content_;
px_width:integer;
px_height:integer;
horz_dpi:integer;
vert_dpi:integer;
End;

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,50 @@
Type xlsxAppProperty = Class
Function Create(file); overload;
Begin
file_ := file;
End;
Function SetAppProps(appProps);
Begin
app_xml := file_.WorkBook().GetXmlFileObj('docProps/app.xml');
node := app_xml.FirstChildElement('Properties');
if not ifObj(node) then return array(1, "node::Properties can't be found");
children_arr := appProps.Marshal()['children'];
for i:=0 to length(children_arr)-1 do
Begin
if children_arr[i]['name'] in array('ScaleCrop', 'LinksUpToDate', 'SharedDoc', 'HyperlinksChanged') then
Begin
children_arr[i]['children'][0]['value'] := children_arr[i]['children'][0]['value'] ? "true" : "false";
End
delete_node := node.FirstChildElement(children_arr[i]['name']);
node.InsertAfterChild(delete_node, children_arr[i]);
node.DeleteChild(delete_node);
End
return array(0, '');
End;
Function GetAppProps();
Begin
app_xml := file_.WorkBook().GetXmlFileObj('docProps/app.xml');
node := app_xml.FirstChildElement('Properties');
marshal := node.Marshal()[0]['children'];
reindex(marshal, marshal[:,'name']);
app_props := TOfficeObj('TAppProperty');
app_props.Application := marshal['Application']['children'][0]['value'];
app_props.DocSecurity := marshal['DocSecurity']['children'][0]['value'];
app_props.ScaleCrop := marshal['DocSecurity']['children'][0]['value'] = "false" ? 0 : 1;
app_props.Company := marshal['Company']['children'][0]['value'];
app_props.LinksUpToDate := marshal['LinksUpToDate']['children'][0]['value'] = "false" ? 0 : 1;
app_props.SharedDoc := marshal['SharedDoc']['children'][0]['value'] = "false" ? 0 : 1;
app_props.AppVersion := marshal['AppVersion']['children'][0]['value'];
return array(0, app_props);
End
class Function NewObject(file);
Begin
return new xlsxAppProperty(file);
End;
private
file_; //TSExcelFile对象
End;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,170 @@
Type xlsxComment = Class
///缺省构造函数
Function Create(sheet,excel); overload;
Begin
authors_ := array();
excel_ := excel;
sheetName_ := sheet;
[rid, commentFileName_, sheetFileName_, relsfile] := excel_.WorkBook().GetRelationshipRid(sheet, '../comments');
if commentFileName_ = '' then Begin
rid++;
rId_ := 'rId' + inttostr(rid);
commentId_ := excel_.WorkBook().GetFilesCount('xl/comments') + 1;
commentFileName_ := '../comments' + inttostr(commentId_) + '.xml';
xlCommentFileName := 'xl/comments' + inttostr(commentId_) + '.xml';
excel_.Zip().Add(xlCommentFileName, excel_.XmlObj().XmlHeader() + '<comments xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"></comments>');
excel_.WorkBook().AddRelationshipRid(relsfile, commentFileName_, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments', rId_);
rid ++;
drawingVML_ := '../drawings/vmlDrawing' + inttostr(commentId_) + '.vml';
drawingVMLFile := 'xl/drawings/vmlDrawing' + inttostr(commentId_) + '.vml';
excel_.Zip().Remove(drawingVMLFile);
excel_.Zip().Add(drawingVMLFile, '<xml
xmlns:oa="urn:schemas-microsoft-com:office:activation"
xmlns:p="urn:schemas-microsoft-com:office:powerpoint"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml">
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="' + inttostr(commentId_) + '"/>
</o:shapelayout>
<v:shapetype id="_x0000_t202" coordsize="21600,21600" o:spt="202" path="m0,0l0,21600,21600,21600,21600,0xe">
<v:stroke joinstyle="miter"/>
<v:path gradientshapeok="t" o:connecttype="rect"/>
</v:shapetype>
</xml>');
excel_.WorkBook().AddRelationshipRid(relsfile, drawingVML_, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing', 'rId' + inttostr(rid));
excel_.WorkBook().AddContentType('application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml', '/' + xlCommentFileName);
excel_.WorkBook().AddContentVml();
sheetXml := excel_.WorkBook().GetSheetXmlfile(sheetName_).FirstChildElement('worksheet');
legacy := sheetXml.FirstChildElement('legacyDrawing');
if not ifObj(legacy) then legacy := sheetXml.InsertEndChild('element', 'legacyDrawing');
legacy.SetAttribute('r:id', 'rId' + inttostr(rid));
End
else Begin
rId_ := 'rId' + inttostr(rid);
xlCommentFileName := 'xl/' + ExtractFileName(commentFileName_);
s := RightStr(xlCommentFileName, length(xlCommentFileName) - 11);
commentId_ := strtoint(leftstr(s, length(s) - 4));
drawingVML_ := './drawings/vmlDrawing' + inttostr(commentId_) + '.vml';
End;
commentXmlFile_ := excel_.WorkBook().GetXmlFileObj(xlCommentFileName);
authors := commentXmlFile_.FirstChildElement('comments').FirstChildElement('authors');
if not ifObj(authors) then
authors := commentXmlFile_.FirstChildElement('comments').InsertEndChild('element', 'authors');
node := authors.FirstChildElement();
i := 0;
while ifObj(node) do Begin
author := node.GetText();
authors_[ author ] := i ++;
node := node.NextElement();
End;
//println('sheet={},commentfile={},vmlfile={}',sheet, commentXmlFile_, drawingVML_);
End;
class Function NewObject(sheet, excel);
Begin
excel_ := excel;
o := excel_.WorkBook().GetSheetObj(sheet);//sheet存在
if not ifObj(o) then return 0;
return new xlsxComment(sheet, excel);
End;
Function AddComment(cell, author, comment);
Begin
authorId := authors_[author];
if not ifint(authorId) then Begin
authorId := length(authors_);
commentXmlFile_.FirstChildElement('comments').FirstChildElement('authors').InsertEndChild('element', 'author', author);//添加作者
authors_[author] := authorId;
End;
if not ifstring(comment) then return array(1, 'comment is not a string');
comments := TOfficeObj('TComments');
comments.Ref := cell;
comments.AuthorId := authorId;
authorObj := comments.AddComment(author + ':');
arr := str2array(comment, '\n');
colCount := length(author)+1;
for i:=0 to length(arr)-1 do Begin
line := TrimRight(arr[i]);
if length(line) > colCount then colCount := length(line);
End;
lineCount := length(arr);
commentObj := comments.AddComment('\n' + comment);
commentObj.Font.Bold := nil;
commentObj.Space := 'preserve';
domData := comments.Marshal();
node := getComment(cell);
if ifObj(node) then
node.DeleteChildren();
else
node := commentXmlFile_.FirstChildElement('comments').FirstChildElement('commentList').InsertEndChild('element', 'comment');
node.UnMarshal(domData);
//commentXmlFile_.print;
innerxml := '<v:shape id="_x0000_s1025" o:spt="202" type="#_x0000_t202" style="position:absolute;left:0pt;top:0pt;margin-left:59.85pt;margin-top:1.5pt;height:60pt;width:97.5pt;visibility:hidden;" fillcolor="#FFFFE1" filled="t" stroked="t" o:insetmode="auto" coordsize="21600,21600">
<v:path/>
<v:fill on="t" color2="#FFFFFF" focussize="0,0"/>
<v:stroke color="#000000"/>
<v:imagedata o:title=""/>
<o:lock v:ext="edit" aspectratio="f"/>
<v:textbox style="direction:context;layout-flow:horizontal;mso-rotate:0;">
<div style="text-align:left"/>
</v:textbox>
<x:ClientData />
</v:shape>';
drawingVMLFile := 'xl/drawings/vmlDrawing' + inttostr(commentId_) + '.vml';
xmlObj := excel_.WorkBook().GetXmlFileObj(drawingVMLFile);
if ifObj(xmlObj) then Begin
node := xmlObj.LastChildElement('xml').InsertEndChild('element','v:shape');
node.UnMarshal(innerxml);
node := node.FirstChildElement('x:ClientData');
if ifObj(node) then Begin
[err, col, row] := excel_.CellNameToCoordinates(cell);
clientData := TOfficeObj('TClientData');
clientData.Anchor := fmt('{},23,{},0,{},{},{},5',col, row, 1+col+lineCount, colCount+col-1, 1+row+lineCount);
clientData.Row := row - 1;
ClientData.Column := col - 1;
node.UnMarshal(clientData.Marshal());
commentObjs_[ length(commentObjs_) ] := array(cell, node);
//xmlObj.Print;
End;
End;
return array(0, 'ok');
End;
Function getComment(cell);
Begin
if not ifarray(commentObjs_) then Begin
commentObjs_ := array();
node := commentXmlFile_.FirstChildElement('comments').FirstChildElement('commentList');
if not ifObj(node) then
node := commentXmlFile_.FirstChildElement('comments').InsertEndChild('element','commentList');
node := node.FirstChildElement('comment');
while ifObj(node) do Begin
ref := node.GetAttribute('ref');
commentObjs_[index++] := array(ref, node);
node := node.NextElement();
End;
End;
return vselect [1] from commentObjs_ where [0] = cell end;
End;
Function RemoveComment(cell);
Begin
node := getComment(cell);
if ifObj(node) then
commentXmlFile_.FirstChildElement('comments').DeleteChild(node);
return array(0, 'ok');
End;
private
authors_;
commentId_;
commentFileName_:string;//'../comments/comment1.xml'
drawingVML_:string;//'../drawings/vmlDrawing1.xml'
rId_:string;
sheetName_:string;//sheet名称
sheetFileName_;//xl/worksheets/sheetN.xml
excel_;//TSExcelFile对象
commentXmlFile_;//XmlFile对象
commentObjs_;
End;

View File

@ -0,0 +1,32 @@
Type xlsxHeaderFooter = Class
Function Create(sheetobj, file, xml);
Begin
sheet_ := sheetobj;
file_ := file;
xmlFile_ := xml;
End
class Function NewObject(sheetname, file);
Begin
o := file.WorkBook().GetSheetObj(sheetname);
xml := file.WorkBook().GetSheetXmlfile(sheetname);
if not ifObj(o) then return 0;
return new xlsxHeaderFooter(o, file, xml);
End;
// 设置sheet的页面页脚
Function SetHeaderFooter(headerFooter);
Begin
node := xmlFile_.FirstChildElement('worksheet');
header_node := node.FirstChildElement('headerFooter');
if ifObj(header_node) then
node.DeleteChild(header_node);
node.InsertEndChild(headerFooter.Marshal());
End
private
sheet_; //XmlSheet对象
file_; //TSExcelFile对象
xmlFile_; //sheet对应的xml对象
End;

View File

@ -0,0 +1,90 @@
Type xlsxHyperLink = Class
Function Create(sheetName, file, xmlFile); overload;
Begin
sheetName_ := sheetName;
file_ := file;
xmlFile_ := xmlFile;
End;
class Function NewObject(sheetname, file);
Begin
xmlFile := file.WorkBook().GetSheetXmlfile(sheetname);
return new xlsxHyperLink(sheetname, file, xmlFile);
End;
Function SetCellHyperLink(axis, hyperlink);
Begin
work_node := xmlFile_.FirstChildElement('worksheet');
hyperlinks := work_node.FirstChildElement('hyperlinks');
if not ifObj(hyperlinks) then begin
phone_node := work_node.FirstChildElement('phoneticPr');
hyperlinks := work_node.InsertAfterChild(phone_node, 'element', 'hyperlinks');
end;
node := hyperlinks.FirstChildElement('hyperlink');
while ifObj(node) do begin
ref := node.GetAttribute('ref');
if ref = axis then begin
node := hyperlinks.DeleteChild(node);
break;
end;
node := node.NextElement();
end;
hyperlink.Axis := axis;
marshal := hyperlink.Marshal();
attrs := marshal['attributes'];
if attrs['linkType'] = "Location" then reindex(attrs, array('linkType': nil, 'linkUrl': 'location'));
else if attrs['linkType'] = "External" then
Begin
[rid, commentFileName, sheetFileName, relsfile] := file_.WorkBook().GetRelationshipRid(sheetName_, hyperlink.LinkUrl);
if commentFileName = "" then
Begin
rid++;
ridstr := 'rId' + inttostr(rid);
xmlfile := file_.WorkBook().GetXmlFileObj(relsfile);
class(xlsxXml).AddRelationshipRid(xmlfile, hyperlink.LinkUrl, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", ridstr, "External");
End
reindex(attrs, array('linkType': nil, 'linkUrl': nil));
attrs['r:id'] := 'rId' + inttostr(rid);
End
marshal['attributes'] := attrs;
hyperlinks.InsertEndChild(marshal);
return array(0,'ok');
End;
Function GetCellHyperLink(axis);
Begin
data := array();
hyperlinks := xmlFile_.FirstChildElement('worksheet').FirstChildElement('hyperlinks');
if not ifObj(hyperlinks) then return array(-1, 'Node::hyperlinks is not exist.');
node := hyperlinks.FirstChildElement('hyperlink');
while ifObj(node) do begin
marshal := node.marshal()[0];
attrs := marshal['attributes'];
if attrs['ref'] = axis then
begin
link := TOfficeObj('THyperLink');
link.LinkType := ifnil(attrs['location']) ? "External" : "Location";
if not ifnil(attrs['location']) then
link.LinkUrl := attrs['location'];
else Begin
rid := attrs['r:id'];
file := 'xl/worksheets/_rels/' + ExtractFileName(LowerCase(sheetName_)) + '.xml.rels';
xmlfile := file_.WorkBook().GetXmlFileObj(file);
relnode := class(xlsxXml).FindRelationship(xmlfile, rid);
if ifObj(relnode) then link.LinkUrl := relnode.GetAttribute('Target');
End
link.Display := attrs['display'];
link.Tooltip := attrs['tooltip'];
return array(0, link);
end;
node := node.NextElement();
end;
return array(-2, "The cell has no hyperlink.");
End;
private
file_; //TSExcelFile对象
xmlFile_;//XmlFile对象
sheetName_;
End;

View File

@ -0,0 +1,48 @@
Type xlsxImage = Class
///缺省构造函数
Function Create(sheet,excel); overload;
Begin
excel_ := excel;
sheetName_ := sheet;
[rid_, imageFileName_, sheetFileName_, xmlRelsFile_] := excel_.WorkBook().GetRelationshipRid(sheet, '../media/image');
End;
class Function NewObject(sheet, excel);
Begin
excel_ := excel;
o := excel_.WorkBook().GetSheetObj(sheet);//sheet存在
if not ifObj(o) then return 0;
return new xlsxImage(sheet, excel);
End;
Function SetSheetBackground(pictrue);
Begin
//if not ifBinary(picture.Image) or length(picture.Image) = 0 then
// raise "Invalid Image Data.";
if imageFileName_ = '' then
Begin
rid_++;
imageId := excel_.WorkBook().GetFilesCount('xl/media/') + 1;
imageName := "../media/image" + inttostr(imageId);
type := 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image';
excel_.WorkBook().AddRelationshipRid(xmlRelsFile_, imageName, type, 'rId' + inttostr(rid_));
End
sheet_xml := excel_.WorkBook().GetSheetXmlfile(sheetName_);
node := sheet_xml.FirstChildElement('worksheet');
picture_node := node.FirstChildElement('picture');
if ifObj(picture_node) then
Begin
node.DeleteChild(picture_node);
End
node := node.InsertEndChild('element', 'picture');
node.SetAttribute('r:id', 'rId' + inttostr(rId_));
End
private
sheetName_:string; //sheet名称
sheetFileName_; //xl/worksheets/sheetN.xml
excel_;//TSExcelFile对象
xmlRelsFile_;
imageFileName_;
rid_;
End;

View File

@ -0,0 +1,45 @@
Type xlsxMargins = Class
Function Create(sheetobj, file, xml); overload;
Begin
sheet_ := sheetobj;
file_ := file;
xmlFile_ := xml;
End;
Function SetPageMargins(margins);
Begin
marshal := margins.Marshal();
work_node := xmlFile_.FirstChild('worksheet');
node := work_node.FirstChild('pageMargins');
work_node.DeleteChild(node);
prev_node := work_node.FirstChild('phoneticPr');
work_node.InsertAfterChild(prev_node, marshal);
End;
Function GetPageMargins();
Begin
node := xmlFile_.FirstChild('worksheet').FirstChild('pageMargins');
marshal := node.Marshal()[0];
margins := TOfficeObj('tmargins');
margins.Bottom := marshal['attributes']['bottom'];
margins.Footer := marshal['attributes']['footer'];
margins.Header := marshal['attributes']['header'];
margins.Left := marshal['attributes']['left'];
margins.Right := marshal['attributes']['right'];
margins.Top := marshal['attributes']['top'];
return margins;
End
class Function NewObject(sheetname, file);
Begin
o := file.WorkBook().GetSheetObj(sheetname);
xml := file.WorkBook().GetSheetXmlfile(sheetname);
if not ifObj(o) then return 0;
return new xlsxMargins(o, file, xml);
End;
private
file_; //TSExcelFile对象
sheet_;//XmlSheet对象
xmlFile_; //sheet对应的xml对象
End;

View File

@ -0,0 +1,65 @@
Type xlsxPageLayout = Class
Function Create(sheetobj, file, xml); overload;
Begin
sheet_ := sheetobj;
file_ := file;
xmlFile_ := xml;
End;
Function SetPageLayout(sheet, pageLayout);
Begin
marshal := pageLayout.Marshal();
work_node := xmlFile_.FirstChild('worksheet');
node := work_node.FirstChild('pageSetUp');
if ifObj(node) then work_node.DeleteChild(node);
workbook_xml := file_.WorkBook().GetXmlFileObj('xl/workbook.xml');
workbook := workbook_xml.FirstChildElement('workbook').FirstChildElement('sheets').FirstChildElement('sheet');
if not ifObj(workbook) then return array(1, 'workbook error!');
while ifObj(workbook) do
Begin
sheet_name := workbook.GetAttribute('name');
if sheet_name = sheet then
Begin
rid := workbook.GetAttribute('r:id');
break;
End
workbook := workbook.NextElement();
End
if not ifnil(marshal['attributes']['firstPageNumber']) then marshal['attributes']['useFirstPageNumber'] := 1;
marshal['attributes']['r:id'] := rid;
work_node.InsertEndChild(marshal);
return array(0, '');
End;
Function GetPageLayout();
Begin
node := xmlFile_.FirstChild('worksheet').FirstChild('pageSetUp');
if not ifObj(node) then return array(1, '<node>: pageSetUp not found');
marshal := node.Marshal()[0];
page_layout := TOfficeObj('TPageLayout');
page_layout.Scale := marshal['attributes']['scale'];
page_layout.FitToWidth := marshal['attributes']['fitToWidth'];
page_layout.FitToHeight := marshal['attributes']['fitToHeight'];
page_layout.PaperSize := marshal['attributes']['paperSize'];
page_layout.Orientation := marshal['attributes']['orientation'];
page_layout.BlackAndWhite := marshal['attributes']['blackAndWhite'];
page_layout.FirstPageNumber := marshal['attributes']['firstPageNumber'];
page_layout.CellError := marshal['attributes']['errors'];
page_layout.CellComments := marshal['attributes']['cellComments'];
page_layout.Draft := marshal['attributes']['draft'];
return page_layout;
End
class Function NewObject(sheetname, file);
Begin
o := file.WorkBook().GetSheetObj(sheetname);
xml := file.WorkBook().GetSheetXmlfile(sheetname);
if not ifObj(o) then return 0;
return new xlsxPageLayout(o, file, xml);
End;
private
file_; //TSExcelFile对象
sheet_;//XmlSheet对象
xmlFile_; //sheet对应的xml对象
End;

View File

@ -0,0 +1,18 @@
Type xlsxRichText = Class
file_; //TSExcelFile对象
sheet_;//XmlSheet对象
Function Create(); overload;
Begin
End;
class Function NewObject(sheetname, self);
Begin
file_ := file;
o = file_.WorkBook().GetSheetObj(sheetname);
if not ifObj(o) then return 0;
richTxt := new xlsxRichText();
richTxt.sheet_ = o;
richTxt.file_ := file;
return richTxt;
End;
End;

View File

@ -0,0 +1,60 @@
Type xlsxSheetView = Class
Function Create(sheetobj, file, xml); overload;
Begin
sheet_ := sheetobj;
file_ := file;
xmlFile_ := xml;
End;
Function SetSheetViewOptions(viewIndex, sheetView);
Begin
node := xmlFile_.FirstChild('worksheet').FirstChild('sheetViews');
sheet_view_node := node.FirstChild('sheetView');
while ifObj(sheet_view_node) do
Begin
id := sheet_view_node.GetAttribute('workbookViewId');
if trystrtoint(id, r) and r = viewIndex then
Begin
marshal := SheetView.Marshal();
class(xlsxXml).UpdateNode(sheet_view_node, marshal['attributes'], array());
return array(0, '');
End
sheet_view_node := sheet_view_node.NextElement();
End
return array(1, 'viewIndex not found : ' $ viewIndex);
End;
Function GetSheetViewOptions(viewIndex, sheetView);
Begin
node := xmlFile_.FirstChild('worksheet').FirstChild('sheetViews');
sheet_view_node := node.FirstChild('sheetView');
while ifObj(sheet_view_node) do
Begin
id := sheet_view_node.GetAttribute('workbookViewId');
if trystrtoint(id, r) and r = viewIndex then
Begin
marshal := sheet_view_node.Marshal()[0];
sheetview := TOfficeObj('TSheetView');
sheetview.ShowGridLines := marshal['attributes']['showGridLines'];
sheetview.ShowRowColHeaders := marshal['attributes']['showRowColHeaders'];
sheetview.ZoomScale := marshal['attributes']['zoomScale'];
sheetview.ZoomScaleNormal := marshal['attributes']['zoomScaleNormal'];
return array(0, sheetView);
End
End
return array(1, 'viewIndex not found : ' $ viewIndex);
End
class Function NewObject(sheetname, file);
Begin
o := file.WorkBook().GetSheetObj(sheetname);
xml := file.WorkBook().GetSheetXmlfile(sheetname);
if not ifObj(o) then return 0;
return new xlsxSheetView(o, file, xml);
End;
private
file_; //TSExcelFile对象
sheet_;//XmlSheet对象
xmlFile_; //sheet对应的xml对象
End;

View File

@ -0,0 +1,107 @@
Type xlsxStyles = Class
Function Create(sheetobj, file);
Begin
sheet_ := sheetobj;
file_ := file;
styleXmlFile_ := file_.WorkBook().GetXmlFileObj('xl/styles.xml');
End
Function GetStyleId(style);
Begin
node := styleXmlFile_.FirstChildElement('styleSheet');
font_id := insertNode(node, 'fonts', style.Font);
border_id := insertNode(node, 'borders', style.Border);
fill_id := insertNode(node, 'fills', style.Fill);
processNumFmtId(node, 'numFmts', style.NumberFormat);
numfmt_id := insertNode(node, 'numFmts', style.NumberFormat);
// 整理插入节点内容
child_arr := array();
alignment_marshal := style.Alignment.Marshal();
if istable(alignment_marshal['children']) or istable(alignment_marshal['attributes']) then
begin
alignment_flag := 1;
child_arr union= array(alignment_marshal);
end
protection_marshal := style.Protection.Marshal();
if istable(protection_marshal['children']) or istable(protection_marshal['attributes']) then
begin
protection_flag := 1;
child_arr union= array(protection_marshal);
end
attr_arr := array(
'numFmtId': style.NumberFormat.NumFmtId ? : "0",
'fontId': font_id,
'fillId': fill_id,
'borderId': border_id,
'xfId': 0,
);
if font_id <> '0' then attr_arr['applyFont'] := '1';
if border_id <> '0' then attr_arr['applyBorder'] := '1';
if numfmt_id <> '0' then attr_arr['applyNumberFormat'] := '1';
if fill_id <> '0' then attr_arr['applyFill'] := '1';
if alignment_flag then attr_arr['applyAlignment'] := '1';
if protection_flag then attr_arr['applyProtection'] := '1';
arr := array('name': 'xf', 'type': 'element',
'attributes': attr_arr,
'children': child_arr,
);
node := node.FirstChildElement('cellXfs');
count := node.GetAttribute('count');
node.InsertEndChild(arr);
node.SetAttribute('count', strtoint(count) + 1);
//node.print;
return count;
End
class Function NewObject(sheetname, file);
Begin
o := file.WorkBook().GetSheetObj(sheetname);
if not ifObj(o) then return 0;
styles := new xlsxStyles(o, file);
return styles;
End;
private
Function insertNode(rootNode, childName, obj);
Begin
marshal := obj.Marshal();
if not istable(marshal['children']) and not istable(marshal['attributes']) then return '0';
node := rootNode.FirstChildElement(childName);
if not ifObj(node) then
begin
info := array('name': childName, 'type': 'element', 'attributes': ('count': '0'));
rootNode.InsertFirstChild(info);
node := rootNode.FirstChildElement(childName);
end
count := node.GetAttribute('count');
node.InsertEndChild(marshal);
node.SetAttribute('count', strtoint(count) + 1);
//node.Print;
return count;
End
Function processNumFmtId(rootNode, childName, obj);
Begin
if ifnil(obj.FormatCode) or not ifnil(obj.numFmtId) then return;
node := rootNode.FirstChildElement(childName);
if not ifObj(node) then obj.numFmtId := '1';
else begin
node := node.LastChildElement('numFmt');
if not ifObj(node) then obj.numFmtId := '1';
else begin
id := node.GetAttribute('numFmtId');
obj.numFmtId := strtoint(id) + 1;
end
end
End
private
sheet_; //XmlSheet对象
file_; //TSExcelFile对象
styleXmlFile_; //xmlFile对象
End;

File diff suppressed because it is too large Load Diff