TSOffice/funcext/TSOffice/worksheet/xlsxComment.tsf

194 lines
7.7 KiB
Plaintext

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, class(TSXml).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));
content_xml := excel_.WorkBook().GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
class(TSXml).AddOverrideContentType(content_xml, '/' + xlCommentFileName, 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml');
class(TSXml).AddDefaultContentType(content_xml, 'vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing');
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;
initCommentObjs();
//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 '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 := commentObjs_[cell];
if ifObj(node) then
node.DeleteChildren();
else
node := commentXmlFile_.FirstChildElement('comments').FirstChildElement('commentList').InsertEndChild('element', 'comment');
node.UnMarshal(domData);
commentObjs_[cell] := node;
//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());
//xmlObj.Print;
End;
End;
return 'ok';
End;
Function GetComment(cell);
Begin
o := commentObjs_[cell];
if not ifObj(o) then return array(nil, nil);
r_node := o.FirstChildElement('text').FirstChildElement('r');
author := r_node.FirstChildElement('t').GetText();
if length(author) > 1 then author := author[:length(author)-1];
r_node := r_node.NextElement();
comment := '';
while ifObj(r_node) do
begin
comment += r_node.FirstChildElement('t').GetText();
r_node := r_node.NextElement();
end
if length(comment) > 1 then comment := comment[2:];
return array(author, comment);
End;
Function RemoveComment(cell);
Begin
node := commentObjs_[cell];
if ifObj(node) then
begin
commentXmlFile_.FirstChildElement('comments').FirstChildElement('commentList').DeleteChild(node);
commentObjs_[cell] := nil;
end
End;
private
Function initCommentObjs();
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_[ref] := node;
node := node.NextElement();
End;
End;
End;
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;