TSOffice/funcext/TSOffice/worksheet/xlsxStyles.tsf

294 lines
9.1 KiB
Plaintext

Type xlsxStyles = Class
Function Create(sheetobj, file);
Begin
sheet_ := sheetobj;
file_ := file;
styleXmlFile_ := file_.WorkBook().GetXmlFileObj('xl/styles.xml');
End
Function GetStyleId(style);overload;
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);
alignment_marshal := style.Alignment.Marshal();
if istable(alignment_marshal['children']) or istable(alignment_marshal['attributes']) then
alignment_flag := 1;
protection_marshal := style.Protection.Marshal();
if istable(protection_marshal['children']) or istable(protection_marshal['attributes']) then
protection_flag := 1;
xf := TOfficeObj('TXf');
xf.NumFmtId := style.NumberFormat.NumFmtId ? : 0;
xf.FontId := font_id;
xf.FillId := fill_id;
xf.BorderId := border_id;
xf.XfId := 0;
xf.ApplyFont := font_id <> '0' ? 1 : nil;
xf.ApplyFill := fill_id <> '0' ? 1 : nil;
xf.ApplyBorder := border_id <> '0' ? 1 : nil;
xf.ApplyAlignment := alignment_flag ?: nil;
xf.ApplyProtection := protection_flag ?: nil;
xf.Alignment := style.Alignment;
xf.Protection := style.Protection;
node := node.FirstChildElement('cellXfs');
count := node.GetAttribute('count');
node.InsertEndChild(xf.Marshal());
node.SetAttribute('count', strtoint(count) + 1);
return count;
End;
Function GetStyleId(newStyle, oldStyleId);overload;
Begin
if oldStyleId = '' then return nil;
style_node := styleXmlFile_.FirstChildElement('styleSheet');
cellXfs_node := style_node.FirstChildElement('cellXfs');
count := strtoint(cellXfs_node.GetAttribute('count'));
Id := strtoint(oldStyleId);
if Id > count-1 then return nil;
xf := getNode(cellXfs_node, 'xf', Id);
marshal := xf.marshal()[0];
xf_node := cellXfs_node.InsertEndChild(marshal);
cellXfs_node.SetAttribute('count', count + 1);
attrs := marshal['attributes'];
style := newStyle;
numfmt_id := trystrtoint(attrs['numFmtId'], r) ? r : 0;
copyNode(style_node, xf_node, 'numFmts', 'numFmt', 'numFmtId', numfmt_id, style.NumberFormat);
font_id := trystrtoint(attrs['fontId'], r) ? r : 0;
copyNode(style_node, xf_node, 'fonts', 'font', 'fontId', font_id, style.Font);
border_id := trystrtoint(attrs['borderId'], r) ? r : 0;
copyNode(style_node, xf_node, 'borders', 'border', 'borderId', border_id, style.Border);
fill_id := trystrtoint(attrs['fillId'], r) ? r : 0;
copyNode(style_node, xf_node, 'fills', 'fill', 'fillId', fill_id, style.Fill);
marshal := style.Alignment.Marshal();
alignment := xf_node.FirstChildElement('alignment');
if ifObj(alignment) then class(TSXml).UpdateNode(alignment, marshal['attributes'], marshal['children']);
else begin
xf_node.InsertEndChild(marshal);
xf_node.SetAttribute('applyAlignment', 1);
end
marshal := style.Protection.Marshal();
protection := xf_node.FirstChildElement('protection');
if ifObj(protection) then class(TSXml).UpdateNode(protection, marshal['attributes'], marshal['children']);
else begin
xf_node.InsertEndChild(marshal);
xf_node.SetAttribute('applyProtection', 1);
end
return inttostr(count);
End;
Function GetStyle(styleId);
Begin
if styleId = '' then return nil;
style_node := styleXmlFile_.FirstChildElement('styleSheet');
cellXfs_node := style_node.FirstChildElement('cellXfs');
count := strtoint(cellXfs_node.GetAttribute('count'));
Id := strtoint(styleId);
if Id > count-1 then return nil;
xf := getNode(cellXfs_node, 'xf', Id);
attrs := xf.Attributes();
numfmt_id := trystrtoint(attrs['numFmtId'], r) ? r : 0;
font_id := trystrtoint(attrs['fontId'], r) ? r : 0;
border_id := trystrtoint(attrs['borderId'], r) ? r : 0;
fill_id := trystrtoint(attrs['fillId'], r) ? r : 0;
alignment := xf.FirstChildElement('alignment');
protection := xf.FirstChildElement('protection');
style := TOfficeObj('TStyle');
numFmts_node := style_node.FirstChildElement('numFmts');
fonts_node := style_node.FirstChildElement('fonts');
borders_node := style_node.FirstChildElement('borders');
fills_node := style_node.FirstChildElement('fills');
setRootObj(style.NumberFormat, getNode(numFmts_node, 'numFmt', numfmt_id));
setRootObj(style.Font, getNode(fonts_node, 'font', font_id));
setRootObj(style.Border, getNode(borders_node, 'border', border_id));
node := getNode(fills_node, 'fill', fill_id);
setRootObj(style.Fill, node);
setFillGradientObj(style.Fill.Gradient, node);
style.Alignment.RootObj := ifObj(alignment) ? alignment : nil;
style.Protection.RootObj := ifObj(protection) ? protection : nil;
setNodeUri(style);
return style;
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 setFillGradientObj(obj, node);
Begin
gradient_node := node.FirstChildElement('gradientFill');
if not ifObj(gradient_node) then return;
stop_node := gradient_node.FirstChildElement('stop');
if ifObj(stop_node) then
begin
obj.Stop1.RootObj := stop_node;
obj.Stop1.NodeUri := '';
end
stop_node := stop_node.NextElement();
if ifObj(stop_node) then
begin
obj.Stop2.RootObj := stop_node;
obj.Stop2.NodeUri := '';
end
stop_node := stop_node.NextElement();
if ifObj(stop_node) then
begin
obj.Stop3.RootObj := stop_node;
obj.Stop3.NodeUri := '';
end
End;
Function setRootObj(obj, node);
Begin
obj.RootObj := node;
children := obj.GetChildren();
for i:=0 to length(children)-1 do
begin
val := children[i]['obj'];
if ifObj(val) then
begin
val.NodeUri := children[i]['name'];
val.RootObj := node;
end
end;
End;
Function setNodeUri(obj);
Begin
obj.NodeUri := '';
children := obj.GetChildren();
for i:=0 to length(children)-1 do
begin
val := children[i]['obj'];
if ifObj(val) then val.NodeUri := '';
end;
End;
Function getNode(rootNode, name, count);
Begin
if name = 'numFmt' then return getNodeNumFmts(rootNode, count);
if not ifObj(rootNode) then return nil;
node := rootNode.FirstChildElement(name);
times := count;
while times > 0 do
begin
node := node.NextElement();
times--;
end
return node;
End;
Function getNodeNumFmts(rootNode, id);
Begin
if not ifObj(rootNode) then return nil;
node := rootNode.FirstChildElement('numFmt');
num_id := inttostr(id);
while ifObj(node) do
begin
if num_id = node.GetAttribute('numFmtId') then return node;
node := node.NextElement();
end
return nil;
End;
Function copyNodeNumFmts(root, xf_node, id, obj);
Begin
if id = 0 then
begin
if ifnil(obj.FormatCode) then xf_node.SetAttribute('numFmtId', 0);
else begin
obj.NumFmtId := 176;
insertNode(root, 'numFmts', obj);
xf_node.SetAttribute('numFmtId', 176);
end
end
else begin
nodeName_node := root.FirstChildElement('numFmts');
println("id = {}", id);
num_node := getNodeNumFmts(nodeName_node, id);
processNumFmtId(root, 'numFmts', obj);
new_node := nodeName_node.InsertEndChild(num_node.Marshal()[0]);
count := strtoint(nodeName_node.GetAttribute('count'));
nodeName_node.SetAttribute('count', count + 1);
xf_node.SetAttribute('numFmtId', obj.NumFmtId);
marshal := obj.Marshal();
class(TSXml).UpdateNode(new_node, marshal['attributes'], marshal['children']);
end
End;
Function copyNode(root, xf_node, nodeName, name, idName, id, obj);
Begin
if nodeName = 'numFmts' then return copyNodeNumFmts(root, xf_node, id, obj);
nodeName_node := root.FirstChildElement(nodeName);
if not ifObj(nodeName_node) then return;
node := getNode(nodeName_node, name, id);
new_node := nodeName_node.InsertEndChild(node.Marshal()[0]);
count := strtoint(nodeName_node.GetAttribute('count'));
nodeName_node.SetAttribute('count', count + 1);
xf_node.SetAttribute(idName, count);
if ifObj(obj) then
begin
marshal := obj.Marshal();
class(TSXml).UpdateNode(new_node, marshal['attributes'], marshal['children']);
end;
End;
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);
return count;
End
Function processNumFmtId(rootNode, childName, obj);
Begin
if ifnil(obj.FormatCode) then return;
node := rootNode.FirstChildElement(childName);
if not ifObj(node) then id := 176;
else begin
node := node.LastChildElement('numFmt');
id := strtoint(node.GetAttribute('numFmtId')) + 1;
end
obj.numFmtId := id;
End
private
sheet_; //XmlSheet对象
file_; //TSExcelFile对象
styleXmlFile_; //xmlFile对象
End;