Function TOfficeApi();
Begin
	if not ifObj(sysparams['TOffice sys api']) then 
		sysparams['TOffice sys api'] := new TOffice();
	return sysparams['TOffice sys api'];
End;

Type TOffice = Class
	Function Create();
	Begin
		hash_ := array();
	End;
	
	///检测当前环境字符集
	///调用规范：TOfficeApi().CodePage('中文');
	Function CodePage(zw);
	Begin
		cp := 'utf8';//默认环境为UTF8格式
		str := StrToBase64(zw);
		case str of
		'1tDOxA==':
			cp := 'gbk';
		'5Lit5paH':
			cp := 'utf8';
		'pKSk5Q==':
			cp := 'big5';
		End;
		hash_['CodePage'] := cp;
	End;
	
	///当前环境是否UTF8
	Function IsUtf8();
	Begin
		if ifnil(hash_['CodePage']) or hash_['CodePage'] = 'utf8' then
			return true;
		return false;
	End;
	
	///UTF8转当前字符集
	Function Utf8ToCurCodePage(str);
	Begin
		if ifstring(str) and not IsUtf8() then
			return UTF8ToAnsi(str);
		return str;
	End;
	
	///当前字符集转UTF8
	Function CurCodePageToUtf8(str);
	Begin
		if ifstring(str) and not IsUtf8() then
			return AnsiToUTF8(str);
		return str;
	End;
	
	///当前字符集转GBK
	Function CurCodePageToGBK(str);
	Begin
		if ifstring(str) and IsUtf8() then
			return UTF8ToAnsi(str);
		return str;
	End;
	
	///获得当前文档对象:TDocxFile对象
	Function GetDocument();
	Begin
		return hash_['Docx'];
	End;
	
	///设置当前段落标签
	///name：string 标签名称
	Function SetParagraphTag(name);
	Begin
		hash_['Paragraph-Node-' + name] := hash_['CurrentParagraph'];
	End;
	
	Function GetCurrentPosition()
	Begin
		return hash_['CurrentPosition'];
	End;
	
	///获取当前TSL代码段所在段落
	///返回：TParagraph对象
	Function GetCurrentParagraph();
	Begin
		node := hash_['CurrentParagraph'];
		if not ifObj(node) then 
			return nil;
		p := TOfficeObj('TParagraph');
		p.Init(node);
		return p;
	End;
	
	///获取当前TSL代码段所在段落的w:r元素
	///返回：TRun对象
	Function GetCurrentRun();
	Begin
		node := hash_['CurrentRun'];
		if not ifObj(node) then 
			return nil;
		p := TOfficeObj('TRun');
		p.Init(node);
		return p;
	End;
	
	///获取指定标签段落
	///name：string 标签名称
	///返回：TParagraph对象
	Function GetParagraph(name);
	Begin
		node := hash_['Paragraph-Node-' + name];
		if not ifObj(node) then 
			return nil;
		p := TOfficeObj('TParagraph');
		p.Init(node);
		return p;
	End;
	
	///获取当前TSL代码段上一个表格
	///[p]：可选参数，为Nil指当前段落
	///返回：TTable对象
	Function GetPrevTable(p);
	Begin
		return getTableImpl(p, false);
	End;
	
	///获取当前TSL代码段下一个表格
	///[p]：可选参数，为Nil指当前段落
	///返回：TTable对象
	Function GetNextTable(p);
	Begin
		return getTableImpl(p, true);
	End;
		
	///获取当前TSL代码段上一张图片
	///[p]：可选参数，为Nil指当前段落
	///返回：TPicture对象
	Function GetPrevPicture(p);
	Begin
		return getPictureImpl(p, false);
	End;
		
	///获取当前TSL代码段下一张图片
	///[p]：可选参数，为Nil指当前段落
	///返回：TPicture对象
	Function GetNextPicture(p);
	Begin
		return getPictureImpl(p, true);
	End;
	
	///获取当前TSL代码段上一个Chart图
	///[p]：可选参数，为Nil指当前段落
	///返回：TChart对象
	Function GetPrevChart(p);
	Begin
		return getChartImpl(p, false);
	End;
	
	///获取当前TSL代码段下一个Chart图
	///[p]：可选参数，为Nil指当前段落
	///返回：TChart对象
	Function GetNextChart(p);
	Begin
		return getChartImpl(p, true);
	End;
	
	///获取当前TSL代码段上一个文本框图
	///[p]：可选参数，为Nil指当前段落
	///返回：TTextBox对象
	Function GetPrevTextBox(p);
	Begin
		p1 := getTextBoxImpl(p, false);
	End;
	
	///获取当前TSL代码段下一个文本框图
	///[p]：可选参数，为Nil指当前段落
	///返回：TTextBox对象
	Function GetNextTextBox(p);
	Begin
		return getTextBoxImpl(p, true);
	End;

	///获取docx的类型
	///普通段落：0
	///图片段落：1
	///表格：2
	///其他：-1
	Function GetDocxPartType(part);
	Begin
		if not ifObj(part) then return -1;
		case part.name_ of
			'w:p':
			begin
				if class(TSXml).GetNode(part.node_, 'w:r/w:drawing') then return 1;
				return 0;
			end
			'w:tbl':
				return 2;
			else
				return -1;
		end;
	End;
	
	Function Set(k, v);
	Begin
		hash_[k] := v;
	End;
	
	Function Get(k);
	Begin
		return hash_[k];
	End;
private
	Function getTableImpl(p, next);
	Begin
		if not ifObj(p) then
			p := GetCurrentParagraph();
		node := next ? p.node_.NextElement('w:tbl') : p.node_.PrevElement('w:tbl');
		if not ifObj(node) then
			return nil;
		tbl := TOfficeObj('TTable');
		tbl.Init(node);
		return tbl;
	End;
	
	Function getPictureImpl(p, next);
	Begin
		if not ifObj(p) then
			p := GetCurrentParagraph();
		node := next ? p.node_.NextElement('w:p') : p.node_.PrevElement('w:p');
		while ifObj(node) do Begin
			draw := class(TSXml).GetNode(node, 'w:r/w:drawing/wp:inline/a:graphic/a:graphicData/pic:pic');
			if ifObj(draw) then Begin
				p := TOfficeObj('TPicture');
				p.Init(node);
				return p;
			End;
			node := next ? p.node.NextElement('w:p') : p.node.PrevElement('w:p');
		End;
		return nil;
	End;
	
	Function getChartImpl(p, next);
	Begin
		if not ifObj(p) then
			p := GetCurrentParagraph();
		node := next ? p.node_.NextElement('w:p') : p.node_.PrevElement('w:p');
		while ifObj(node) do Begin
			chartNode := class(TSXml).GetNode(node, 'w:r/w:drawing/wp:inline/a:graphic/a:graphicData/c:chart');
			if ifObj(chartNode) then Begin
				p := TOfficeObj('TChart');
				p.Init(hash_['Docx'], node, chartNode);
				return p;
			End;
			node := next ? p.node.NextElement('w:p') : p.node.PrevElement('w:p');
		End;
		return nil;
	End;
	
	Function getTextBoxImpl(p, next);
	Begin
		if not ifObj(p) then
			p := GetCurrentParagraph();
		node := next ? p.node_.NextElement('w:p') : p.node_.PrevElement('w:p');
		while ifObj(node) do Begin
			p := TOfficeObj('TParagraph');
			boxs := p.TextBoxs();
			if istable(boxs) then Begin
				if next then return boxs[0];
				return boxs[ length(boxs) - 1];
			End;
			node := next ? p.node.NextElement('w:p') : p.node.PrevElement('w:p');
		End;
		return nil;
	End;
	
	hash_;
End;
