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

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

	Function SetSheetBackground(pic);
	Begin
		if not ifBinary(pic.Image) or length(pic.Image) = 0 then
			return "Invalid Image Data.";
		picture := new TSImage(pic.Image);

		image_file := getImageFileName(picture);
		rels_xmlfile := excel_.WorkBook().GetSheetRelsFile(sheetName_);
		prefix := ReplaceStr(image_file, 'xl/', '../');
		//println("image_file = {}", image_file);
		[rid, target] := class(TSXml).FindRelationshipRid(rels_xmlfile, prefix);
		if target = '' then
		begin
			rid ++;
			class(TSXml).AddRelationshipRid(rels_xmlfile, prefix, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', 'rId' $ rid);
		end
		content_xml := excel_.WorkBook().GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
		class(TSXml).AddDefaultContentType(content_xml, picture.ExtFileName, 'image/' $ picture.ExtFileName);

		sheet_xml := excel_.WorkBook().GetSheetXmlfile(sheetName_);
		node := sheet_xml.FirstChildElement('worksheet');
		picture_node := node.FirstChildElement('picture');
		if not ifObj(picture_node) then
		begin
			prev_node := class(TSXml).GetWorkSheetPrevNode(node, 'picture');
			if ifObj(prev_node) then picture_node := node.InsertAfterChild(prev_node, 'element', 'picture');
			else picture_node := node.InsertEndChild('element', 'picture');
		end
		picture_node.SetAttribute('r:id', 'rId' + inttostr(rid));
	End

	Function AddPicture(topLeft, bottomRight, pic, format);
	Begin
		if not ifBinary(pic.Image) or length(pic.Image) = 0 then
			return "Invalid Image Data.";
		picture := new TSImage(pic.Image);
		[err1, col1, row1] := excel_.CellNameToCoordinates(topLeft);
		[err2, col2, row2] := excel_.CellNameToCoordinates(bottomRight);
		if err1 or err2 then return 'Invalid params.';

		image_target := ReplaceStr(getImageFileName(picture), 'xl/', '../');
		drawing_id := excel_.WorkBook().GetSheetDrawing(sheetName_);
		drawing_rels := excel_.WorkBook().GetDrawingRelsFile(drawing_id);
		[rid, target] := class(TSXml).FindRelationshipRid(drawing_rels, image_target);
		if target = '' then
		begin
			rid++;
			class(TSXml).AddRelationshipRid(drawing_rels, image_target, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', 'rId' $ rid);
		end
		content_xml := excel_.WorkBook().GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
		class(TSXml).AddDefaultContentType(content_xml, picture.ExtFileName, 'image/' $ picture.ExtFileName);
		sheet_xml := excel_.WorkBook().GetSheetXmlfile(sheetName_);
		node := sheet_xml.FirstChildElement('worksheet');
		drawing_node := node.FirstChildElement('drawing');
		if not ifObj(drawing_node) then
		begin
			prev_node := class(TSXml).GetWorkSheetPrevNode(node, 'drawing');
			if ifObj(prev_node) then drawing_node := node.InsertAfterChild(prev_node, 'element', 'drawing');
			else drawing_node := node.InsertEndChild('element', 'drawing');
		end
		sheet_rels := excel_.WorkBook().GetSheetRelsFile(sheetName_);
		drawing_file_name := '../drawings/drawing' + inttostr(drawing_id) + '.xml';
		[id, target] := class(TSXml).FindRelationshipRid(sheet_rels, drawing_file_name);
		drawing_node.SetAttribute('r:id', 'rId' + inttostr(id));

		// drawingN.xml
		drawing_xml := excel_.WorkBook().GetXmlFileObj('xl/drawings/drawing' $ drawing_id $ ".xml");
		if not ifObj(format) then format := TOfficeObj('TPictureFormat');

		o := TOfficeObj('TtwoCellAnchor');
		o.EditAs := 'oneCell';
		o.XFrom.Col := col1;
		o.XFrom.ColOff := format.BegColOff;
		o.XFrom.Row := row1;
		o.XFrom.RowOff := format.BegRowOff;
		o.XTo.Col := col2;
		o.XTo.ColOff := format.EndColOff;
		o.XTo.Row := row2;
		o.XTo.RowOff := format.EndRowOff;

		o.Pic.NodeName := 'xdr:pic';
		o.Pic.NvPicPr.NodeName := 'xdr:nvPicPr';
		o.Pic.NvPicPr.CNvPr.Name := picture.Name ? picture.Name : '';
		o.Pic.NvPicPr.CNvPr.ID := class(TSXml).GetcNvPrID(drawing_xml);
		o.Pic.NvPicPr.CNvPr.ExtLst.Ext.Uri := '';
		o.Pic.NvPicPr.CNvPr.ExtLst.Ext.Xmlns16 := 'http://schemas.microsoft.com/office/drawing/2014/main';
		o.Pic.NvPicPr.CNvPr.Replace(array("pic:": "xdr:"));
		o.Pic.NvPicPr.CNvPicPr.PicLocks := "1";
		o.Pic.BlipFill.NodeName := 'xdr:blipFill';
		o.Pic.BlipFill.Blip.Xmlns := "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
		o.Pic.BlipFill.Blip.Embed := 'rId' + inttostr(rid);
		o.Pic.BlipFill.Stretch.FillRect := true;
		o.Pic.SpPr.XFrm.Off.X := 0;
		o.Pic.SpPr.XFrm.Off.Y := 0;
		o.Pic.SpPr.XFrm.Ext.Cx := 0;
		o.Pic.SpPr.XFrm.Ext.CY := 0;
		o.Pic.SpPr.NodeName := 'xdr:spPr';
		o.Pic.SpPr.PrstGeom.Prst := "rect";
		o.Pic.SpPr.PrstGeom.AvLst := true;

		drawing_xml.FirstChildElement('xdr:wsDr').InsertEndChild(o.Marshal());
	End

	Function DeletePicture(topLeft, bottomRight);
	Begin
		[err1, col1, row1] := excel_.CellNameToCoordinates(topLeft);
		[err2, col2, row2] := excel_.CellNameToCoordinates(bottomRight);
		if err1 or err2 then return 'Invalid params.';

		drawing_id := excel_.WorkBook().GetSheetDrawing(sheetName_);
		drawing_xml := excel_.WorkBook().GetXmlFileObj('xl/drawings/drawing' $ drawing_id $ ".xml");
		if not ifObj(drawing_xml) then return 'drawing xml is not exist.';
		wsDr_node := drawing_xml.FirstChildElement('xdr:wsDr');
		node := wsDr_node.FirstChildElement('xdr:twoCellAnchor');
		while ifObj(node) do
		begin
			from_node := node.FirstChildElement('xdr:from');
			to_node := node.FirstChildElement('xdr:to');
			from_col := strtoint(from_node.FirstChildElement('xdr:col').GetText());
			from_row := strtoint(from_node.FirstChildElement('xdr:row').GetText());
			to_col := strtoint(to_node.FirstChildElement('xdr:col').GetText());
			to_row := strtoint(to_node.FirstChildElement('xdr:row').GetText());
			if (col1 <= from_col and row1 <= from_row) and (col2 + 1 > to_col and row2 + 1 > to_row) then
				prev := node;
			node := node.NextElement();
			if ifObj(prev) then wsDr_node.DeleteChild(prev);
		end
	End

private

	Function getImageFileName(picture);
	Begin
		image_files := sselect ['FileName'] from zipfile_.Files() where AnsiStartsText('xl/media/image', ['FileName']) end;
		image_file := '';
		for i:=0 to length(image_files)-1 do
		begin
			if zipfile_.Diff(image_files[i], picture.Content) = 0 then
			begin
				image_file := image_files[i];
				break;
			end
		end
		if image_file = '' then
		begin
			image_count := length(image_files) + 1;
			image_file := 'xl/media/image' $ image_count $ '.' $ picture.ExtFileName;
			zipfile_.Add(image_file, picture.Content);
		end
		return image_file;
	End

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