You've already forked lazarus-ccr
fpspreadsheet: Add custom meta data support. Reading/writing for XLSX, Excel XML, ODS.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7591 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -58,6 +58,7 @@ end;
|
|||||||
var
|
var
|
||||||
book: TsWorkbook;
|
book: TsWorkbook;
|
||||||
sheet: TsWorksheet;
|
sheet: TsWorksheet;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
book := TsWorkbook.Create;
|
book := TsWorkbook.Create;
|
||||||
try
|
try
|
||||||
@ -72,6 +73,8 @@ begin
|
|||||||
book.MetaData.Comments.Add('Assign the creation date to the field CreatedAt.');
|
book.MetaData.Comments.Add('Assign the creation date to the field CreatedAt.');
|
||||||
book.MetaData.Keywords.Add('Test');
|
book.MetaData.Keywords.Add('Test');
|
||||||
book.MetaData.Keywords.Add('FPSpreadsheet');
|
book.MetaData.Keywords.Add('FPSpreadsheet');
|
||||||
|
book.MetaData.AddCustom('Comparny', 'Disney');
|
||||||
|
book.MetaData.AddCustom('Status', 'finished');
|
||||||
|
|
||||||
sheet := book.AddWorksheet('Test');
|
sheet := book.AddWorksheet('Test');
|
||||||
sheet.WriteText(2, 3, 'abc');
|
sheet.WriteText(2, 3, 'abc');
|
||||||
@ -86,9 +89,9 @@ begin
|
|||||||
book := TsWorkbook.Create;
|
book := TsWorkbook.Create;
|
||||||
try
|
try
|
||||||
// Select one of these
|
// Select one of these
|
||||||
book.ReadFromFile('test.ods');
|
// book.ReadFromFile('test.ods');
|
||||||
// book.ReadFromFile('test.xlsx');
|
// book.ReadFromFile('test.xlsx');
|
||||||
// book.ReadFromFile('test.xml');
|
book.ReadFromFile('test.xml');
|
||||||
WriteLn('Created by : ', book.MetaData.CreatedBy);
|
WriteLn('Created by : ', book.MetaData.CreatedBy);
|
||||||
WriteLn('Date created : ', DateTimeToStr(book.MetaData.DateCreated));
|
WriteLn('Date created : ', DateTimeToStr(book.MetaData.DateCreated));
|
||||||
WriteLn('Modified by : ', book.MetaData.LastModifiedBy);
|
WriteLn('Modified by : ', book.MetaData.LastModifiedBy);
|
||||||
@ -96,6 +99,9 @@ begin
|
|||||||
WriteLn('Title : ', book.MetaData.Title);
|
WriteLn('Title : ', book.MetaData.Title);
|
||||||
WriteLn('Subject : ', book.MetaData.Subject);
|
WriteLn('Subject : ', book.MetaData.Subject);
|
||||||
WriteLn('Keywords : ', book.MetaData.Keywords.CommaText);
|
WriteLn('Keywords : ', book.MetaData.Keywords.CommaText);
|
||||||
|
WriteLn('Custom : ', 'Name':20, 'Value':20);
|
||||||
|
for i := 0 to book.MetaData.Custom.Count-1 do
|
||||||
|
WriteLn(' ', book.MetaData.Custom.Names[i]:20, book.MetaData.Custom.ValueFromIndex[i]:20);
|
||||||
WriteLn('Comments: ');
|
WriteLn('Comments: ');
|
||||||
WriteLn(book.MetaData.Comments.Text);
|
WriteLn(book.MetaData.Comments.Text);
|
||||||
finally
|
finally
|
||||||
|
@ -1966,6 +1966,7 @@ var
|
|||||||
book: TsWorkbook;
|
book: TsWorkbook;
|
||||||
nodeName: String;
|
nodeName: String;
|
||||||
s: String;
|
s: String;
|
||||||
|
name: String;
|
||||||
begin
|
begin
|
||||||
book := TsWorkbook(FWorkbook);
|
book := TsWorkbook(FWorkbook);
|
||||||
|
|
||||||
@ -1992,6 +1993,12 @@ begin
|
|||||||
book.MetaData.Title := s;
|
book.MetaData.Title := s;
|
||||||
'dc:subject':
|
'dc:subject':
|
||||||
book.Metadata.Subject := s;
|
book.Metadata.Subject := s;
|
||||||
|
'meta:user-defined':
|
||||||
|
begin
|
||||||
|
name := GetAttrValue(ANode, 'meta:name');
|
||||||
|
if name <> '' then
|
||||||
|
book.MetaData.AddCustom(name, s);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
ANode := ANode.NextSibling;
|
ANode := ANode.NextSibling;
|
||||||
end;
|
end;
|
||||||
@ -5911,6 +5918,16 @@ begin
|
|||||||
'<dc:description>%s</dc:description>', [s]));
|
'<dc:description>%s</dc:description>', [s]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if book.MetaData.Custom.Count > 0 then
|
||||||
|
begin
|
||||||
|
for i := 0 to book.Metadata.Custom.Count-1 do
|
||||||
|
AppendToStream(FSMeta, Format(
|
||||||
|
'<meta:user-defined meta:name="%s">%s</meta:user-defined>', [
|
||||||
|
book.Metadata.Custom.Names[i],
|
||||||
|
book.Metadata.Custom.ValueFromIndex[i]
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
AppendToStream(FSMeta,
|
AppendToStream(FSMeta,
|
||||||
'</office:meta>');
|
'</office:meta>');
|
||||||
AppendToStream(FSMeta,
|
AppendToStream(FSMeta,
|
||||||
|
@ -976,9 +976,12 @@ type
|
|||||||
FSubject: String;
|
FSubject: String;
|
||||||
FComments: TStrings;
|
FComments: TStrings;
|
||||||
FKeywords: TStrings;
|
FKeywords: TStrings;
|
||||||
|
FCustom: TStrings;
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
function AddCustom(AName, AValue: String): Integer;
|
||||||
|
procedure Clear;
|
||||||
function IsEmpty: Boolean;
|
function IsEmpty: Boolean;
|
||||||
property CreatedBy: String read FCreatedBy write FCreatedBy;
|
property CreatedBy: String read FCreatedBy write FCreatedBy;
|
||||||
property LastModifiedBy: String read FLastModifiedBy write FLastModifiedBy;
|
property LastModifiedBy: String read FLastModifiedBy write FLastModifiedBy;
|
||||||
@ -987,6 +990,7 @@ type
|
|||||||
property Subject: String read FSubject write FSubject;
|
property Subject: String read FSubject write FSubject;
|
||||||
property Title: String read FTitle write FTitle;
|
property Title: String read FTitle write FTitle;
|
||||||
property Comments: TStrings read FComments write FComments;
|
property Comments: TStrings read FComments write FComments;
|
||||||
|
property Custom: TStrings read FCustom write FCustom;
|
||||||
property Keywords: TStrings read FKeywords write FKeywords;
|
property Keywords: TStrings read FKeywords write FKeywords;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1199,20 +1203,44 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
FComments := TStringList.Create;
|
FComments := TStringList.Create;
|
||||||
FKeywords := TStringList.Create;
|
FKeywords := TStringList.Create;
|
||||||
|
FCustom := TStringList.Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TsMetaData.Destroy;
|
destructor TsMetaData.Destroy;
|
||||||
begin
|
begin
|
||||||
FComments.Free;
|
FComments.Free;
|
||||||
FKeywords.Free;
|
FKeywords.Free;
|
||||||
|
FCustom.Free;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsMetaData.Clear;
|
||||||
|
begin
|
||||||
|
FTitle := '';
|
||||||
|
FSubject := '';
|
||||||
|
FCreatedBy := '';
|
||||||
|
FLastModifiedBy := '';
|
||||||
|
FDateCreated := 0;
|
||||||
|
FDateLastModified := 0;
|
||||||
|
FComments.Clear;
|
||||||
|
FKeywords.Clear;
|
||||||
|
FCustom.Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsMetaData.AddCustom(AName, AValue: String): Integer;
|
||||||
|
begin
|
||||||
|
Result := FCustom.IndexOf(AName);
|
||||||
|
if result > -1 then
|
||||||
|
FCustom.ValueFromIndex[Result] := AValue
|
||||||
|
else
|
||||||
|
Result := FCustom.Add(AName + '=' + AValue);
|
||||||
|
end;
|
||||||
|
|
||||||
function TsMetaData.IsEmpty: Boolean;
|
function TsMetaData.IsEmpty: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := (FCreatedBy = '') and (FLastModifiedBy = '') and
|
Result := (FCreatedBy = '') and (FLastModifiedBy = '') and
|
||||||
(FTitle = '') and (FSubject = '') and
|
(FTitle = '') and (FSubject = '') and
|
||||||
(FComments.Count = 0) and (FKeywords.Count = 0) and
|
(FComments.Count = 0) and (FKeywords.Count = 0) and (FCustom.Count = 0) and
|
||||||
(FDateCreated = 0) and (FDateLastModified = 0);
|
(FDateCreated = 0) and (FDateLastModified = 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ type
|
|||||||
procedure ReadCellProtection(ANode: TDOMNode; var AFormat: TsCellFormat);
|
procedure ReadCellProtection(ANode: TDOMNode; var AFormat: TsCellFormat);
|
||||||
procedure ReadComment(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; ACell: PCell);
|
procedure ReadComment(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; ACell: PCell);
|
||||||
procedure ReadConditionalFormatting(ANode: TDOMNode; AWorksheet: TsBasicWorksheet);
|
procedure ReadConditionalFormatting(ANode: TDOMNode; AWorksheet: TsBasicWorksheet);
|
||||||
|
procedure ReadCustomDocumentProperties(ANode: TDOMNode);
|
||||||
procedure ReadDocumentProperties(ANode: TDOMNode);
|
procedure ReadDocumentProperties(ANode: TDOMNode);
|
||||||
procedure ReadExcelWorkbook(ANode: TDOMNode);
|
procedure ReadExcelWorkbook(ANode: TDOMNode);
|
||||||
procedure ReadFont(ANode: TDOMNode; var AFormat: TsCellFormat);
|
procedure ReadFont(ANode: TDOMNode; var AFormat: TsCellFormat);
|
||||||
@ -96,6 +97,7 @@ type
|
|||||||
procedure WriteConditionalFormat(AStream: TStream; AWorksheet: TsBasicWorksheet;
|
procedure WriteConditionalFormat(AStream: TStream; AWorksheet: TsBasicWorksheet;
|
||||||
AFormat: TsConditionalFormat);
|
AFormat: TsConditionalFormat);
|
||||||
procedure WriteConditionalFormatting(AStream: TStream; AWorksheet: TsBasicWorksheet);
|
procedure WriteConditionalFormatting(AStream: TStream; AWorksheet: TsBasicWorksheet);
|
||||||
|
procedure WriteCustomDocumentProperties(AStream: TStream);
|
||||||
procedure WriteDocumentProperties(AStream: TStream);
|
procedure WriteDocumentProperties(AStream: TStream);
|
||||||
procedure WriteExcelWorkbook(AStream: TStream);
|
procedure WriteExcelWorkbook(AStream: TStream);
|
||||||
procedure WriteNames(AStream: TStream; AWorksheet: TsBasicWorksheet);
|
procedure WriteNames(AStream: TStream; AWorksheet: TsBasicWorksheet);
|
||||||
@ -1100,6 +1102,32 @@ begin
|
|||||||
sheet.WriteConditionalCellFormat(range, TsCFCondition(condition), op1, op2, fmtIndex);
|
sheet.WriteConditionalCellFormat(range, TsCFCondition(condition), op1, op2, fmtIndex);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Read the custom meta data fields
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsSpreadExcelXMLReader.ReadCustomDocumentProperties(ANode: TDOMNode);
|
||||||
|
var
|
||||||
|
book: TsWorkbook;
|
||||||
|
value: String;
|
||||||
|
nodeName: String;
|
||||||
|
begin
|
||||||
|
if ANode = nil then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
book := TsWorkbook(FWorkbook);
|
||||||
|
ANode := ANode.FirstChild;
|
||||||
|
while ANode <> nil do
|
||||||
|
begin
|
||||||
|
nodeName := ANode.NodeName;
|
||||||
|
if nodeName <> '#text' then
|
||||||
|
begin
|
||||||
|
value := GetNodeValue(ANode);
|
||||||
|
book.MetaData.AddCustom(nodeName, value);
|
||||||
|
end;
|
||||||
|
ANode := ANode.NextSibling;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Reads the meta data etc.
|
Reads the meta data etc.
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
@ -2069,6 +2097,7 @@ begin
|
|||||||
|
|
||||||
// Read meta data
|
// Read meta data
|
||||||
ReadDocumentProperties(doc.DocumentElement.FindNode('DocumentProperties'));
|
ReadDocumentProperties(doc.DocumentElement.FindNode('DocumentProperties'));
|
||||||
|
ReadCustomDocumentProperties(doc.DocumentElement.FindNode('CustomDocumentProperties'));
|
||||||
|
|
||||||
// Read style list
|
// Read style list
|
||||||
ReadStyles(doc.DocumentElement.FindNode('Styles'));
|
ReadStyles(doc.DocumentElement.FindNode('Styles'));
|
||||||
@ -2680,6 +2709,33 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadExcelXMLWriter.WriteCustomDocumentProperties(AStream: TStream);
|
||||||
|
{ <CustomDocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
|
||||||
|
<Comparny dt:dt="string">Disney</Comparny>
|
||||||
|
<Status dt:dt="string">finished</Status>
|
||||||
|
</CustomDocumentProperties> }
|
||||||
|
var
|
||||||
|
book: TsWorkbook;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
book := TsWorkbook(FWorkbook);
|
||||||
|
if book.MetaData.Custom.Count = 0 then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
AppendToStream(AStream, INDENT1 +
|
||||||
|
'<CustomDocumentProperties xmlns="urn:schemas-microsoft-com:office:office">' + LF);
|
||||||
|
|
||||||
|
for i := 0 to book.MetaData.Custom.Count-1 do
|
||||||
|
AppendToStream(AStream, Format(INDENT2 +
|
||||||
|
'<%0:s dt:dt="string">%1:s</%0:s>' + LF, [
|
||||||
|
book.MetaData.Custom.Names[i],
|
||||||
|
book.MetaData.Custom.ValueFromIndex[i]
|
||||||
|
]));
|
||||||
|
|
||||||
|
AppendToStream(AStream, INDENT1 +
|
||||||
|
'</CustomDocumentProperties>' + LF);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadExcelXMLWriter.WriteDateTime(AStream: TStream;
|
procedure TsSpreadExcelXMLWriter.WriteDateTime(AStream: TStream;
|
||||||
const ARow, ACol: Cardinal; const AValue: TDateTime; ACell: PCell);
|
const ARow, ACol: Cardinal; const AValue: TDateTime; ACell: PCell);
|
||||||
var
|
var
|
||||||
@ -2719,8 +2775,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadExcelXMLWriter.WriteDocumentProperties(AStream: TStream);
|
procedure TsSpreadExcelXMLWriter.WriteDocumentProperties(AStream: TStream);
|
||||||
const
|
|
||||||
LE = LineEnding;
|
|
||||||
var
|
var
|
||||||
sTitle: String;
|
sTitle: String;
|
||||||
sSubject: String;
|
sSubject: String;
|
||||||
@ -2733,32 +2787,30 @@ var
|
|||||||
begin
|
begin
|
||||||
book := TsWorkbook(FWorkbook);
|
book := TsWorkbook(FWorkbook);
|
||||||
|
|
||||||
if (book.MetaData.Title = '') and
|
if book.MetaData.IsEmpty then
|
||||||
(book.MetaData.CreatedBy = '') and (book.MetaData.LastModifiedBy = '') and
|
|
||||||
(book.MetaData.DateCreated <= 0) and (book.MetaData.DateLastModified <= 0) then
|
|
||||||
begin
|
begin
|
||||||
AppendToStream(AStream, INDENT1 +
|
AppendToStream(AStream, INDENT1 +
|
||||||
'<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office" />' + LE);
|
'<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office" />' + LF);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if book.MetaData.Title <> '' then
|
if book.MetaData.Title <> '' then
|
||||||
sTitle := '<Title>' + book.MetaData.Title + '</Title>' + LE + INDENT2
|
sTitle := '<Title>' + book.MetaData.Title + '</Title>' + LF + INDENT2
|
||||||
else
|
else
|
||||||
sTitle := '';
|
sTitle := '';
|
||||||
|
|
||||||
if book.MetaData.Subject <> '' then
|
if book.MetaData.Subject <> '' then
|
||||||
sSubject := '<Subject>' + book.MetaData.Subject + '</Subject>' + LE + INDENT2
|
sSubject := '<Subject>' + book.MetaData.Subject + '</Subject>' + LF + INDENT2
|
||||||
else
|
else
|
||||||
sSubject := '';
|
sSubject := '';
|
||||||
|
|
||||||
if book.MetaData.CreatedBy <> '' then
|
if book.MetaData.CreatedBy <> '' then
|
||||||
sAuthor := '<Author>' + book.MetaData.CreatedBy + '</Author>' + LE + INDENT2
|
sAuthor := '<Author>' + book.MetaData.CreatedBy + '</Author>' + LF + INDENT2
|
||||||
else
|
else
|
||||||
sAuthor := '';
|
sAuthor := '';
|
||||||
|
|
||||||
if book.MetaData.LastModifiedBy <> '' then
|
if book.MetaData.LastModifiedBy <> '' then
|
||||||
sLastAuthor := '<LastAuthor>' + book.MetaData.LastModifiedBy + '</LastAuthor>' + LE + INDENT2
|
sLastAuthor := '<LastAuthor>' + book.MetaData.LastModifiedBy + '</LastAuthor>' + LF + INDENT2
|
||||||
else
|
else
|
||||||
sLastAuthor := '';
|
sLastAuthor := '';
|
||||||
|
|
||||||
@ -2766,7 +2818,7 @@ begin
|
|||||||
if book.MetaData.DateCreated > 0 then begin
|
if book.MetaData.DateCreated > 0 then begin
|
||||||
dt := book.MetaData.DateCreated + GetLocalTimeOffset / (24*60);
|
dt := book.MetaData.DateCreated + GetLocalTimeOffset / (24*60);
|
||||||
sDateCreated := FormatDateTime(ISO8601FormatExtendedUTC, dt);
|
sDateCreated := FormatDateTime(ISO8601FormatExtendedUTC, dt);
|
||||||
sDateCreated := '<Created>' + sDateCreated + '</Created>' + LE + INDENT2;
|
sDateCreated := '<Created>' + sDateCreated + '</Created>' + LF + INDENT2;
|
||||||
end else
|
end else
|
||||||
sDateCreated := '';
|
sDateCreated := '';
|
||||||
|
|
||||||
@ -2774,20 +2826,20 @@ begin
|
|||||||
begin
|
begin
|
||||||
dt := book.MetaData.DateLastModified + GetLocalTimeOffset / (24*60);
|
dt := book.MetaData.DateLastModified + GetLocalTimeOffset / (24*60);
|
||||||
sDateLastSaved := FormatDateTime(ISO8601FormatExtendedUTC, dt);
|
sDateLastSaved := FormatDateTime(ISO8601FormatExtendedUTC, dt);
|
||||||
sDateLastSaved := '<LastSaved>' + sDateLastSaved + '</LastSaved>' + LE + INDENT2;
|
sDateLastSaved := '<LastSaved>' + sDateLastSaved + '</LastSaved>' + LF + INDENT2;
|
||||||
end else
|
end else
|
||||||
sDateLastSaved := '';
|
sDateLastSaved := '';
|
||||||
|
|
||||||
AppendToStream(AStream, INDENT1 +
|
AppendToStream(AStream, INDENT1 +
|
||||||
'<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">' + LE + INDENT2 +
|
'<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">' + LF + INDENT2 +
|
||||||
sTitle +
|
sTitle +
|
||||||
sSubject +
|
sSubject +
|
||||||
sAuthor +
|
sAuthor +
|
||||||
sLastAuthor +
|
sLastAuthor +
|
||||||
sDateCreated +
|
sDateCreated +
|
||||||
sDateLastSaved +
|
sDateLastSaved +
|
||||||
'<Version>16.00</Version>' + LE + Indent1 +
|
'<Version>16.00</Version>' + LF + INDENT1 +
|
||||||
'</DocumentProperties>' + LE
|
'</DocumentProperties>' + LF
|
||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3397,9 +3449,11 @@ begin
|
|||||||
' xmlns:o="urn:schemas-microsoft-com:office:office"' + LF +
|
' xmlns:o="urn:schemas-microsoft-com:office:office"' + LF +
|
||||||
' xmlns:x="urn:schemas-microsoft-com:office:excel"' + LF +
|
' xmlns:x="urn:schemas-microsoft-com:office:excel"' + LF +
|
||||||
' xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"' + LF +
|
' xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"' + LF +
|
||||||
|
' xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"' + LF +
|
||||||
' xmlns:html="http://www.w3.org/TR/REC-html40">' + LF);
|
' xmlns:html="http://www.w3.org/TR/REC-html40">' + LF);
|
||||||
|
|
||||||
WriteDocumentProperties(AStream);
|
WriteDocumentProperties(AStream);
|
||||||
|
WriteCustomDocumentProperties(AStream);
|
||||||
WriteOfficeDocumentSettings(AStream);
|
WriteOfficeDocumentSettings(AStream);
|
||||||
WriteExcelWorkbook(AStream);
|
WriteExcelWorkbook(AStream);
|
||||||
WriteStyles(AStream);
|
WriteStyles(AStream);
|
||||||
|
@ -173,6 +173,7 @@ type
|
|||||||
procedure WriteComments(AWorksheet: TsBasicWorksheet);
|
procedure WriteComments(AWorksheet: TsBasicWorksheet);
|
||||||
procedure WriteConditionalFormat(AStream: TStream; AFormat: TsConditionalFormat; var APriority: Integer);
|
procedure WriteConditionalFormat(AStream: TStream; AFormat: TsConditionalFormat; var APriority: Integer);
|
||||||
procedure WriteConditionalFormats(AStream: TStream; AWorksheet: TsBasicWorksheet);
|
procedure WriteConditionalFormats(AStream: TStream; AWorksheet: TsBasicWorksheet);
|
||||||
|
procedure WriteCustomMetaData(AStream: TStream);
|
||||||
procedure WriteDefinedNames(AStream: TStream);
|
procedure WriteDefinedNames(AStream: TStream);
|
||||||
procedure WriteDifferentialFormat(AStream: TStream; AFormat: PsCellFormat);
|
procedure WriteDifferentialFormat(AStream: TStream; AFormat: PsCellFormat);
|
||||||
procedure WriteDifferentialFormats(AStream: TStream);
|
procedure WriteDifferentialFormats(AStream: TStream);
|
||||||
@ -217,6 +218,7 @@ type
|
|||||||
FSWorkbook: TStream;
|
FSWorkbook: TStream;
|
||||||
FSWorkbookRels: TStream;
|
FSWorkbookRels: TStream;
|
||||||
FSMetaData: TStream;
|
FSMetaData: TStream;
|
||||||
|
FSCustomMetaData: TStream;
|
||||||
FSStyles: TStream;
|
FSStyles: TStream;
|
||||||
FSSharedStrings: TStream;
|
FSSharedStrings: TStream;
|
||||||
FSSharedStrings_complete: TStream;
|
FSSharedStrings_complete: TStream;
|
||||||
@ -307,6 +309,7 @@ const
|
|||||||
OOXML_PATH_XL_THEME = 'xl/theme/theme1.xml';
|
OOXML_PATH_XL_THEME = 'xl/theme/theme1.xml';
|
||||||
OOXML_PATH_XL_MEDIA = 'xl/media/';
|
OOXML_PATH_XL_MEDIA = 'xl/media/';
|
||||||
OOXML_PATH_DOCPROPS_CORE = 'docProps/core.xml';
|
OOXML_PATH_DOCPROPS_CORE = 'docProps/core.xml';
|
||||||
|
OOXML_PATH_DOCPROPS_CUSTOM = 'docProps/custom.xml';
|
||||||
|
|
||||||
{ OOXML schemas constants }
|
{ OOXML schemas constants }
|
||||||
SCHEMAS_TYPES = 'http://schemas.openxmlformats.org/package/2006/content-types';
|
SCHEMAS_TYPES = 'http://schemas.openxmlformats.org/package/2006/content-types';
|
||||||
@ -314,6 +317,7 @@ const
|
|||||||
SCHEMAS_DOC_RELS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
|
SCHEMAS_DOC_RELS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
|
||||||
SCHEMAS_DOCUMENT = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument';
|
SCHEMAS_DOCUMENT = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument';
|
||||||
SCHEMAS_META_CORE = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
|
SCHEMAS_META_CORE = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
|
||||||
|
SCHEMAS_META_CUSTOM = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
|
||||||
SCHEMAS_WORKSHEET = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet';
|
SCHEMAS_WORKSHEET = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet';
|
||||||
SCHEMAS_STYLES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles';
|
SCHEMAS_STYLES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles';
|
||||||
SCHEMAS_STRINGS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings';
|
SCHEMAS_STRINGS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings';
|
||||||
@ -330,6 +334,7 @@ const
|
|||||||
MIME_RELS = 'application/vnd.openxmlformats-package.relationships+xml';
|
MIME_RELS = 'application/vnd.openxmlformats-package.relationships+xml';
|
||||||
MIME_OFFICEDOCUMENT = 'application/vnd.openxmlformats-officedocument';
|
MIME_OFFICEDOCUMENT = 'application/vnd.openxmlformats-officedocument';
|
||||||
MIME_CORE = 'application/vnd.openxmlformats-package.core-properties+xml';
|
MIME_CORE = 'application/vnd.openxmlformats-package.core-properties+xml';
|
||||||
|
MIME_CUSTOM = 'application/vnd.openxmlformats-officedocument.custom-properties+xml';
|
||||||
MIME_SPREADML = MIME_OFFICEDOCUMENT + '.spreadsheetml';
|
MIME_SPREADML = MIME_OFFICEDOCUMENT + '.spreadsheetml';
|
||||||
MIME_SHEET = MIME_SPREADML + '.sheet.main+xml';
|
MIME_SHEET = MIME_SPREADML + '.sheet.main+xml';
|
||||||
MIME_WORKSHEET = MIME_SPREADML + '.worksheet+xml';
|
MIME_WORKSHEET = MIME_SPREADML + '.worksheet+xml';
|
||||||
@ -2695,9 +2700,11 @@ end;
|
|||||||
|
|
||||||
procedure TsSpreadOOXMLReader.ReadMetaData(ANode: TDOMNode);
|
procedure TsSpreadOOXMLReader.ReadMetaData(ANode: TDOMNode);
|
||||||
var
|
var
|
||||||
|
childNode: TDOMNode;
|
||||||
nodeName: string;
|
nodeName: string;
|
||||||
book: TsWorkbook;
|
book: TsWorkbook;
|
||||||
s: String;
|
s: String;
|
||||||
|
name: String;
|
||||||
dt: TDateTime;
|
dt: TDateTime;
|
||||||
fs: TFormatSettings;
|
fs: TFormatSettings;
|
||||||
begin
|
begin
|
||||||
@ -2714,6 +2721,7 @@ begin
|
|||||||
nodeName := ANode.NodeName;
|
nodeName := ANode.NodeName;
|
||||||
s := GetNodeValue(ANode);
|
s := GetNodeValue(ANode);
|
||||||
case nodeName of
|
case nodeName of
|
||||||
|
// These fields are from "core.xml"
|
||||||
'dc:title':
|
'dc:title':
|
||||||
book.MetaData.Title := s;
|
book.MetaData.Title := s;
|
||||||
'dc:subject':
|
'dc:subject':
|
||||||
@ -2740,6 +2748,21 @@ begin
|
|||||||
'dcterms:modified':
|
'dcterms:modified':
|
||||||
if s <> '' then
|
if s <> '' then
|
||||||
book.MetaData.DateLastModified :=ISO8601StrToDateTime(s);
|
book.MetaData.DateLastModified :=ISO8601StrToDateTime(s);
|
||||||
|
|
||||||
|
// This field is from "custom.xml"
|
||||||
|
'property':
|
||||||
|
begin
|
||||||
|
name := GetAttrValue(ANode, 'name');
|
||||||
|
childNode := ANode.Firstchild;
|
||||||
|
while childNode <> nil do
|
||||||
|
begin
|
||||||
|
nodeName := childNode.NodeName;
|
||||||
|
s := GetNodeValue(childNode);
|
||||||
|
if (s <> '') then
|
||||||
|
book.MetaData.AddCustom(name, s);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
ANode := ANode.NextSibling;
|
ANode := ANode.NextSibling;
|
||||||
end;
|
end;
|
||||||
@ -3798,6 +3821,18 @@ begin
|
|||||||
finally
|
finally
|
||||||
XMLStream.Free;
|
XMLStream.Free;
|
||||||
end;
|
end;
|
||||||
|
// custom meta data
|
||||||
|
XMLStream := CreateXMLStream;
|
||||||
|
try
|
||||||
|
if UnzipToStream(AStream, OOXML_PATH_DOCPROPS_CUSTOM, XMLStream) then
|
||||||
|
begin
|
||||||
|
ReadXMLStream(Doc, XMLStream);
|
||||||
|
ReadMetaData(Doc.DocumentElement);
|
||||||
|
FreeAndNil(Doc);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
XMLStream.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
finally
|
finally
|
||||||
FreeAndNil(Doc);
|
FreeAndNil(Doc);
|
||||||
@ -4516,6 +4551,37 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadOOXMLWriter.WriteCustomMetaData(AStream: TStream);
|
||||||
|
var
|
||||||
|
book: TsWorkbook;
|
||||||
|
i: Integer;
|
||||||
|
id: Integer;
|
||||||
|
begin
|
||||||
|
book := TsWorkbook(FWorkbook);
|
||||||
|
if book.MetaData.Custom.Count = 0 then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" ' +
|
||||||
|
'xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">');
|
||||||
|
|
||||||
|
id := 2;
|
||||||
|
for i := 0 to book.MetaData.Custom.Count-1 do
|
||||||
|
begin
|
||||||
|
AppendToStream(AStream, Format(
|
||||||
|
'<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="%d" name="%s">' +
|
||||||
|
'<vt:lpwstr>%s</vt:lpwstr>' +
|
||||||
|
'</property>', [
|
||||||
|
id, book.MetaData.Custom.Names[i],
|
||||||
|
book.MetaData.Custom.ValueFromIndex[i]
|
||||||
|
]));
|
||||||
|
inc(id);
|
||||||
|
end;
|
||||||
|
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'</Properties>');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOOXMLWriter.WriteDimension(AStream: TStream;
|
procedure TsSpreadOOXMLWriter.WriteDimension(AStream: TStream;
|
||||||
AWorksheet: TsBasicWorksheet);
|
AWorksheet: TsBasicWorksheet);
|
||||||
var
|
var
|
||||||
@ -6084,18 +6150,29 @@ begin
|
|||||||
|
|
||||||
{ --- meta data ---- }
|
{ --- meta data ---- }
|
||||||
WriteMetaData(FSMetaData);
|
WriteMetaData(FSMetaData);
|
||||||
|
WriteCustomMetaData(FSCustomMetaData);
|
||||||
|
|
||||||
{ --- _rels/.rels --- }
|
{ --- _rels/.rels --- }
|
||||||
AppendToStream(FSRelsRels,
|
AppendToStream(FSRelsRels,
|
||||||
XML_HEADER + LineEnding);
|
XML_HEADER + LineEnding);
|
||||||
|
|
||||||
AppendToStream(FSRelsRels, Format(
|
AppendToStream(FSRelsRels, Format(
|
||||||
'<Relationships xmlns="%s">' + LineEnding, [SCHEMAS_RELS]));
|
'<Relationships xmlns="%s">' + LineEnding,
|
||||||
AppendToStream(FSRelsRels, Format(
|
[SCHEMAS_RELS]));
|
||||||
'<Relationship Id="rId2" Target="docProps/core.xml" Type="%s" />' + LineEnding,
|
|
||||||
[SCHEMAS_META_CORE]));
|
|
||||||
AppendToStream(FSRelsRels, Format(
|
AppendToStream(FSRelsRels, Format(
|
||||||
'<Relationship Id="rId1" Target="xl/workbook.xml" Type="%s" />' + LineEnding,
|
'<Relationship Id="rId1" Target="xl/workbook.xml" Type="%s" />' + LineEnding,
|
||||||
[SCHEMAS_DOCUMENT]));
|
[SCHEMAS_DOCUMENT]));
|
||||||
|
|
||||||
|
AppendToStream(FSRelsRels, Format(
|
||||||
|
'<Relationship Id="rId2" Target="docProps/core.xml" Type="%s" />' + LineEnding,
|
||||||
|
[SCHEMAS_META_CORE]));
|
||||||
|
|
||||||
|
if TsWorkbook(FWorkbook).MetaData.Custom.Count > 0 then
|
||||||
|
AppendToStream(FSRelsRels, Format(
|
||||||
|
'<Relationship Id="rId3" Target="docProps/custom.xml" Type="%s" />' + LineEnding,
|
||||||
|
[SCHEMAS_META_CUSTOM]));
|
||||||
|
|
||||||
AppendToStream(FSRelsRels,
|
AppendToStream(FSRelsRels,
|
||||||
'</Relationships>');
|
'</Relationships>');
|
||||||
|
|
||||||
@ -6378,6 +6455,10 @@ begin
|
|||||||
AppendToStream(FSContentTypes,
|
AppendToStream(FSContentTypes,
|
||||||
'<Override PartName="/docProps/core.xml" ContentType="' + MIME_CORE + '" />');
|
'<Override PartName="/docProps/core.xml" ContentType="' + MIME_CORE + '" />');
|
||||||
|
|
||||||
|
if book.MetaData.Custom.Count > 0 then
|
||||||
|
AppendToStream(FSContentTypes,
|
||||||
|
'<Override PartName="/docProps/custom.xml" ContentType="' + MIME_CUSTOM + '" />');
|
||||||
|
|
||||||
AppendToStream(FSContentTypes,
|
AppendToStream(FSContentTypes,
|
||||||
'</Types>');
|
'</Types>');
|
||||||
end;
|
end;
|
||||||
@ -6808,6 +6889,7 @@ begin
|
|||||||
FSSharedStrings := CreateTempStream(FWorkbook, 'fpsSS');
|
FSSharedStrings := CreateTempStream(FWorkbook, 'fpsSS');
|
||||||
FSSharedStrings_complete := CreateTempStream(FWorkbook, 'fpsSSC');
|
FSSharedStrings_complete := CreateTempStream(FWorkbook, 'fpsSSC');
|
||||||
FSMetaData := CreateTempStream(FWorkbook, 'fpsMETA');
|
FSMetaData := CreateTempStream(FWorkbook, 'fpsMETA');
|
||||||
|
FSCustomMetaData := CreateTempStream(FWorkbook, 'fpsCM');
|
||||||
{
|
{
|
||||||
if boFileStream in FWorkbook.Options then
|
if boFileStream in FWorkbook.Options then
|
||||||
begin
|
begin
|
||||||
@ -6848,6 +6930,7 @@ procedure TsSpreadOOXMLWriter.DestroyStreams;
|
|||||||
var
|
var
|
||||||
stream: TStream;
|
stream: TStream;
|
||||||
begin
|
begin
|
||||||
|
DestroyTempStream(FSCustomMetaData);
|
||||||
DestroyTempStream(FSMetaData);
|
DestroyTempStream(FSMetaData);
|
||||||
DestroyTempStream(FSContentTypes);
|
DestroyTempStream(FSContentTypes);
|
||||||
DestroyTempStream(FSRelsRels);
|
DestroyTempStream(FSRelsRels);
|
||||||
@ -6897,6 +6980,7 @@ begin
|
|||||||
ResetStream(FSStyles);
|
ResetStream(FSStyles);
|
||||||
ResetStream(FSSharedStrings_complete);
|
ResetStream(FSSharedStrings_complete);
|
||||||
ResetStream(FSMetaData);
|
ResetStream(FSMetaData);
|
||||||
|
ResetStream(FSCustomMetaData);
|
||||||
for i:=0 to High(FSSheets) do ResetStream(FSSheets[i]);
|
for i:=0 to High(FSSheets) do ResetStream(FSSheets[i]);
|
||||||
for i:=0 to High(FSSheetRels) do ResetStream(FSSheetRels[i]);
|
for i:=0 to High(FSSheetRels) do ResetStream(FSSheetRels[i]);
|
||||||
for i:=0 to High(FSComments) do ResetStream(FSComments[i]);
|
for i:=0 to High(FSComments) do ResetStream(FSComments[i]);
|
||||||
@ -6964,6 +7048,8 @@ begin
|
|||||||
if FSSharedStrings_complete.Size > 0 then
|
if FSSharedStrings_complete.Size > 0 then
|
||||||
FZip.Entries.AddFileEntry(FSSharedStrings_complete, OOXML_PATH_XL_STRINGS);
|
FZip.Entries.AddFileEntry(FSSharedStrings_complete, OOXML_PATH_XL_STRINGS);
|
||||||
FZip.Entries.AddFileEntry(FSMetaData, OOXML_PATH_DOCPROPS_CORE);
|
FZip.Entries.AddFileEntry(FSMetaData, OOXML_PATH_DOCPROPS_CORE);
|
||||||
|
if TsWorkbook(FWorkbook).MetaData.Custom.Count > 0 then
|
||||||
|
FZip.Entries.AddFileEntry(FSCustomMetaData, OOXML_PATH_DOCPROPS_CUSTOM);
|
||||||
|
|
||||||
// Write embedded images
|
// Write embedded images
|
||||||
WriteMedia(FZip);
|
WriteMedia(FZip);
|
||||||
|
Reference in New Issue
Block a user