// MyCell - version 1.1
// Written by Yanxueming <yanxm2003@hotmail.com>
// Copyright (C) 2006-2007
// All rights reserved.
//
// The code and information is provided "as-is" without
// warranty of any kind, either expressed or implied.
//Yanxm 2007��12��6�� 11:16:58
#include "stdafx.h"
#include "../include/XmlMyCell.h"
namespace mycell{
//BOOL ReadIntFromAttribute(MSXML2::IXMLDOMElement* pE,BSTR bstrAttrName,int& val)
//{
// CComVariant v;
// pE->getAttribute(bstrAttrName,&v);
// if(VT_BSTR==v.vt && SUCCEEDED(v.ChangeType(VT_I4))){
// val=v.lVal;
// return TRUE;
// }
// return FALSE;
//}
void XmlMyCell::StyleE2BorderStyle(MSXML2::IXMLDOMElement* pE,Border& bdr)
{
CComVariant v;
pE->getAttribute(L"LineStyle",&v);
if(VT_BSTR==v.vt){
const EXlLineStyle ls=EXlLineStyleFromString(v.bstrVal);
bdr.put_LineStyle(ls);
}
v.Clear();
pE->getAttribute(L"Weight",&v);
if(VT_BSTR==v.vt && SUCCEEDED(v.ChangeType(VT_I1))){
bdr.put_Weight(v.bVal);
}
}
void XmlMyCell::StyleE2StyleDesc(MSXML2::IXMLDOMNode* pStyleN,StyleDesc& sd)
{
{//Alignment
CComPtr<MSXML2::IXMLDOMNode> pN;
pStyleN->selectSingleNode(L"Alignment",&pN);
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(pE){
CComVariant v;
pE->getAttribute(L"Horizontal",&v);
if(v.vt==VT_BSTR){
sd.Align_SetHorizontal(EXlHAlignFromStr(v.bstrVal));
}
v.Clear();
pE->getAttribute(L"Vertical",&v);
if(v.vt==VT_BSTR){
sd.Align_SetVertical(EXlVAlignFromStr(v.bstrVal));
}
v.Clear();
pE->getAttribute(L"WrapText",&v);
if(v.vt==VT_BSTR){
sd.Align_SetWrapText(CComBSTR(v.bstrVal)==L"0"?FALSE:TRUE);
}
}
}
{//Font
CComPtr<MSXML2::IXMLDOMNode> pN;
pStyleN->selectSingleNode(L"Font",&pN);
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(pE){
LOGFONT& lf=sd.Font_GetLogFont();
CComVariant v;
pE->getAttribute(L"FontName",&v);
if(v.vt==VT_BSTR){
lstrcpy(lf.lfFaceName,(LPCTSTR)CString(v.bstrVal));
}
v.Clear();
pE->getAttribute(L"CharSet",&v);
if(v.vt==VT_BSTR && SUCCEEDED(v.ChangeType(VT_UI1))){
lf.lfCharSet=v.bVal;
}
pE->getAttribute(L"Size",&v);
if(v.vt==VT_BSTR && SUCCEEDED(v.ChangeType(VT_I4))){
lf.lfHeight=v.lVal;
}
pE->getAttribute(L"Bold",&v);
if(v.vt==VT_BSTR && SUCCEEDED(v.ChangeType(VT_I4))){
sd.Font_SetBold(v.lVal);
}
pE->getAttribute(L"StrikeThrough",&v);
if(v.vt==VT_BSTR && SUCCEEDED(v.ChangeType(VT_I1))){
lf.lfStrikeOut=v.bVal;
}
pE->getAttribute(L"Italic",&v);
if(v.vt==VT_BSTR && SUCCEEDED(v.ChangeType(VT_I1))){
lf.lfItalic=v.bVal;
}
}
}
{//Borders
CComPtr<MSXML2::IXMLDOMNodeList> pNL;
pStyleN->selectNodes(L"Borders/Border",&pNL);
pNL->reset();
CComPtr<MSXML2::IXMLDOMNode> pN;
Borders* pbdrs=sd.GetBorders();
for(pNL->nextNode(&pN);pN;pN.Release(),pNL->nextNode(&pN)){
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(pE){
CComVariant vp;
pE->getAttribute(L"Position",&vp);
if(VT_BSTR==vp.vt){
const CComBSTR bstrPos(vp.bstrVal);
if(bstrPos==L"Left")
StyleE2BorderStyle(pE,pbdrs->left);
if(bstrPos==L"Top")
StyleE2BorderStyle(pE,pbdrs->top);
if(bstrPos==L"Right")
StyleE2BorderStyle(pE,pbdrs->right);
if(bstrPos==L"Bottom")
StyleE2BorderStyle(pE,pbdrs->bottom);
}
}
}
}
}
HRESULT XmlMyCell::LoadStyles(Worksheet* pGrid,RowHeader& rh,ColHeader& ch,map<StyleID_t,StyleDesc>& mapStyle,MSXML2::IXMLDOMElement* pStylesE)
{
HRESULT hr=S_OK;
StyleDesc defStyle=pGrid->Style_GetTableStyle();
CComPtr<MSXML2::IXMLDOMNode> pN;
pStylesE->get_firstChild(&pN);
//pStylesE->selectSingleNode(L"Style[ID=\"Default\"]",&pN);
if(pN){
StyleE2StyleDesc(pN,defStyle);
pGrid->Style_SetTableStyle(defStyle);
}
CComPtr<MSXML2::IXMLDOMNodeList> pNL;
pStylesE->selectNodes(L"Style",&pNL);
//CComPtr<MSXML2::IXMLDOMNode> pN;
pN.Release();
pNL->reset();
for(pNL->nextNode(&pN);pN;pN.Release(),pNL->nextNode(&pN)){
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(!pE)
continue;
CComVariant v;
pE->getAttribute(L"ID",&v);
StyleID_t nStyleID=0;
if(VT_BSTR==v.vt){
CString str(v.bstrVal);
if(str==_T("Default") || str.GetLength()<2)
continue;
str=str.Right(str.GetLength()-1);
CComVariant vid(str);
if(SUCCEEDED(vid.ChangeType(VT_I2))){
nStyleID=vid.iVal;
}else continue;
}else
continue;
StyleDesc style=defStyle;
StyleE2StyleDesc(pN,style);
mapStyle[nStyleID]=style;
//const StyleID_t nNewStyleID=pGrid->add_style(style);
//mapO2N[nStyleID]=nNewStyleID;
}
return hr;
}
HRESULT XmlMyCell::LoadColumns(Worksheet* pGrid,RowHeader& rh,ColHeader& ch,const map<StyleID_t,StyleDesc>& mapStyle,MSXML2::IXMLDOMElement* pColumnsE)
{
HRESULT hr=S_OK;
CComPtr<MSXML2::IXMLDOMNodeList> pNL;
pColumnsE->get_childNodes(&pNL);
int nPreCol=-1;
pNL->reset();
CComPtr<MSXML2::IXMLDOMNode> pN;
for(pNL->nextNode(&pN);pN;pN.Release(),pNL->nextNode(&pN)){
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(!pE)
continue;
int col=-1;
CComVariant v;
pE->getAttribute(L"idx",&v);
if(VT_BSTR==v.vt){
v.ChangeType(VT_I4);
col=v.lVal;
nPreCol=col;
}else{
col=++nPreCol;
}
v.Clear();
pE->getAttribute(L"l",&v);
if(VT_BSTR==v.vt){
ch.put_ColLabel(col,(LPCTSTR)CString(v.bstrVal));
}
v.Clear();
pE->getAttribute(L"wi",&v);
if(VT_BSTR==v.vt && SUCCEEDED(v.ChangeType(VT_R8))){
const int wi=this->X_Point2Pixel(v.dblVal);
pGrid->put_ColWidth(col,wi,FALSE,FALSE);
}
}
return hr;
}
HRESULT LoadCells(Worksheet* pGrid,RowHeader& rh,ColHeader& ch,int row,const map<StyleID_t,StyleDesc>& mapStyle,MSXML2::IXMLDOMElement* pRowE)
{
HRESULT hr=S_OK;
CComPtr<MSXML2::IXMLDOMNodeList> pNL;
pRowE->get_childNodes(&pNL);
int nPreCol=-1;
pNL->reset();
CComPtr<MSXML2::IXMLDOMNode> pN;
for(pNL->nextNode(&pN);pN;pN.Release(),pNL->nextNode(&pN)){
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(!pE)
continue;
CComVariant v;
int col=-1,nMergeAcross=0,nMergeDown=0;
pE->getAttribute(L"ma",&v);
if(VT_BSTR==v.vt && SUCCEEDED(v.ChangeType(VT_I4))){
nMergeAcross=v.lVal;
}
v.Clear();
pE->getAttribute(L"md",&v);
if(VT_BSTR==v.vt && SUCCEEDED(v.ChangeType(VT_I4))){
nMergeDown=v.lVal;
}
v.Clear();
pE->getAttribute(L"idx",&v);
if(VT_BSTR==v.vt){
v.ChangeType(VT_I4);
col=v.lVal;
//nPreCol=col;
}else{
//col=nMergeAcross?nPreCol+nMergeAcross:nPreCol+1;
col=nPreCol+1;
}
nPreCol=col+nMergeAcross;
v.Clear();
pE->getAttribute(L"t",&v);
if(VT_BSTR==v.vt){
pGrid->SetCellText(row,col,(LPCTSTR)CString(v.bstrVal),FALSE);
}
const StyleDesc* pStyle=NULL;
v.Clear();
pE->getAttribute(L"sid",&v);
if(VT_BSTR==v.vt){
CString str(v.bstrVal);
if(str.GetLength()>1){
str=str.Right(str.GetLength()-1);
v=str;
if(SUCCEEDED(v.ChangeType(VT_I2))){
const StyleID_t nStyleID=v.iVal;
map<StyleID_t,StyleDesc>::const_iterator it=mapStyle.find(nStyleID);
if(it!=mapStyle.end()){
pStyle=&it->second;
pGrid->Style_SetCellStyle(CellID(row,col),it->second);
}
}
}
}
if(nMergeAcross || nMergeDown){
const int maxr=row+nMergeDown;
const int maxc=col+nMergeAcross;
pGrid->MergeCells(row,col,maxr,maxc);
if(pStyle){
for(int r=row;r<=maxr;++r){
for(int c=col;c<=maxc;++c)
if(r!=row && c!=c)
pGrid->Style_SetCellStyle(CellID(r,c),*pStyle);
}
}
}
}
return hr;
}
HRESULT XmlMyCell::LoadRows(Worksheet* pGrid,RowHeader& rh,ColHeader& ch,const map<StyleID_t,StyleDesc>& mapStyle,MSXML2::IXMLDOMElement* pRowsE)
{
HRESULT hr=S_OK;
CComPtr<MSXML2::IXMLDOMNodeList> pNL;
pRowsE->get_childNodes(&pNL);
int nPreRow=-1;
pNL->reset();
CComPtr<MSXML2::IXMLDOMNode> pN;
for(pNL->nextNode(&pN);pN;pN.Release(),pNL->nextNode(&pN)){
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(!pE)
continue;
int row=-1;
CComVariant v;
pE->getAttribute(L"idx",&v);
if(VT_BSTR==v.vt){
v.ChangeType(VT_I4);
row=v.lVal;
nPreRow=row;
}else{
row=++nPreRow;
}
v.Clear();
pE->getAttribute(L"hi",&v);
if(VT_BSTR==v.vt && SUCCEEDED(v.ChangeType(VT_R8))){
const int hi=this->Y_Point2Pixel(v.dblVal);
pGrid->put_RowHeight(row,hi,FALSE,FALSE);
}
LoadCells(pGrid,rh,ch,row,mapStyle,pE);
}
return hr;
}
HRESULT XmlMyCell::load(Worksheet* pGrid,LPCTSTR lpszFile)
{
HRESULT hr=S_OK;
CComPtr<MSXML2::IXMLDOMDocument> pXmlDoc;
if FAILED(hr=pXmlDoc.CoCreateInstance(MSXML2::CLSID_DOMDocument))
return hr;
const CComVariant bstrXml(lpszFile);
VARIANT_BOOL bSucc;
if(FAILED(hr=pXmlDoc->load(bstrXml,&bSucc)))
return hr;
if(!bSucc){
if FAILED(hr=pXmlDoc->loadXML(CComBSTR(lpszFile),&bSucc))
return hr;
}
if(!bSucc){
return AtlReportError(CLSID_NULL,L"�����ļ�ʧ�ܣ�",GUID_NULL,E_FAIL);
}
RowHeader& rh=pGrid->get_RowHeader();
ColHeader& ch=pGrid->get_ColHeader();
pGrid->clear();
//pGrid->ClearStyles();
//pGrid->put_rows(1);
//pGrid->put_cols(1);
map<StyleID_t,StyleDesc> mapStyle;
{//load GridProperties properties
CComPtr<MSXML2::IXMLDOMNode> pN;
pXmlDoc->selectSingleNode(L"mycell/GridProperties",&pN);
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(pE){
int rows=0,cols=0;//,nDefaultColumnWidth=0,nDefaultRowHeight=0;
if(ReadIntFromAttribute(pE,L"Rows",rows)){
pGrid->put_rows(rows);
}else
return hr;
if(ReadIntFromAttribute(pE,L"Cols",cols)){
pGrid->put_cols(cols);
}else
return hr;
double dx;
if(ReadDoubleFromAttribute(pE,L"DefaultColumnWidth",dx)){
const int nDefaultColumnWidth=X_Point2Pixel(dx);
ch.put_DefColWidth(nDefaultColumnWidth);
}
if(ReadDoubleFromAttribute(pE,L"DefaultRowHeight",dx)){
const int nDefaultRowHeight=this->Y_Point2Pixel(dx);
rh.put_DefRowHeight(nDefaultRowHeight);
}
}else
return hr;
}
{//load styles properties
CComPtr<MSXML2::IXMLDOMNode> pN;
pXmlDoc->selectSingleNode(L"mycell/Styles",&pN);
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(pE){
hr=LoadStyles(pGrid,rh,ch,mapStyle,pE);
}
}
{//load columns properties
CComPtr<MSXML2::IXMLDOMNode> pN;
pXmlDoc->selectSingleNode(L"mycell/Columns",&pN);
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(pE){
hr=LoadColumns(pGrid,rh,ch,mapStyle,pE);
}
}
{//load Rows properties
CComPtr<MSXML2::IXMLDOMNode> pN;
pXmlDoc->selectSingleNode(L"mycell/Rows",&pN);
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
if(pE){
hr=LoadRows(pGrid,rh,ch,mapStyle,pE);
}
}
pGrid->put_TopVisScrollRow(0);
pGrid->put_LeftVisScrollCol(0);
pGrid->Scroll_ResetHScrollBar();//TRUE,TRUE);
pGrid->Scroll_ResetVScrollBar();
//pGrid->Scroll_ResetScrollBars(TRUE,TRUE);
return hr;
}
CComPtr<MSXML2::IXMLDOMElement> XmlMyCell::CreateStyleNode(MSXML2::IXMLDOMDocument* pXmlDoc,BSTR bstrStyleNodeName,MSXML2::IXMLDOMElement* pStylesE/*,CComPtr<MSXML2::IXMLDOMElement>& pStyleE*/)
{
CComPtr<MSXML2::IXMLDOMNode> _pN;
pStylesE->selectSingleNode(bstrStyleNodeName,&_pN);
CComQIPtr<MSXML2::IXMLDOMElement> pStyleE=_pN;
if(!pStyleE){
//AppendTextNode(pXmlDoc,pStylesE,L"\r\n\t\t");
pXmlDoc->createElement(bstrStyleNodeName,&pStyleE);
pStylesE->appendChild(pStyleE,NULL);
}
return pStyleE;
}
void XmlMyCell::CreateBorderNode(MSXML2::IXMLDOMDocument* pXmlDoc,MSXML2::IXMLDOMElement* pBordersE,const Border* bdr,BSTR bstrPos)
{
const EXlLineStyle ls=bdr->get_LineStyle();
const CComBSTR bstrLineStyle(EXlLineStyleToString(ls));
if(bstrLineStyle.Length()>0){
CComPtr<MSXML2::IXMLDOMNode> pN;
CComBSTR sql(L"Border[@Position=\"");sql.Append(bstrPos);sql.Append(L"\"]");
pBordersE->selectSingleNode(sql,&pN);
CComQIPtr<MSXML2::IXMLDOMElement> pBorderE=pN;
if(!pBorderE){
pXmlDoc->createElement(L"Border",&pBorderE);
pBordersE->appendChild(pBorderE,NULL);
}
pBorderE->setAttribute(L"Position",CComVariant(bstrPos));
pBorderE->setAttribute(L"LineStyle",CComVariant(bstrLineStyle));
pBorderE->setAttribute(L"Weight",CComVariant(bdr->get_Weight()));
RemoveEmptyAttributeNode(pBordersE,pBorderE);
}
}
HRESULT XmlMyCell::_SaveStyles(const StyleDesc& sd,MSXML2::IXMLDOMDocument* pXmlDoc,MSXML2::IXMLDOMElement* pE,const StyleDesc* pDefStyle)
{
const EXlVAlign va=sd.Align_GetVertical();
const EXlHAlign ha=sd.Align_GetHorizontal();
const BOOL bWrapText=sd.Align_IsWrapText()?1:0;
const CComBSTR bstrVAlignment(EXlVAlignToStr(va));
const CComBSTR bstrHAlignment(EXlHAlignToStr(ha));
{//Alignment properties
CComPtr<MSXML2::IXMLDOMElement> _pE=CreateStyleNode(pXmlDoc,L"Alignment",pE);
{
if(!pDefStyle || pDefStyle->Align_GetHorizontal()!=ha)
_pE->setAttribute(L"Horizontal",CComVariant(bstrHAlignment));
if(!pDefStyle || pDefStyle->Align_GetVertical()!=va)
_pE->setAttribute(L"Vertical",CComVariant(bstrVAlignment));
if(!pDefStyle || pDefStyle->Align_IsWrapText()!=bWrapText)
_pE->setAttribute(L"WrapText",CComVariant(bWrapText));
}
RemoveEmptyAttributeNode(pE,_pE);
}
{//Font properties
CComPtr<MSXML2::IXMLDOMElement> _pE=CreateStyleNode(pXmlDoc,L"Font",pE);
const LOGFONT& lf=sd.Font_GetLogFont();
const LOGFONT* lfDef=pDefStyle?&pDefStyle->Font_GetLogFont():NULL;
if(!lfDef || lstrcmp(lfDef->lfFaceName,lf.lfFaceName))
_pE->setAttribute(L"FontName",CComVariant(lf.lfFaceName));
if(!lfDef || lfDef->lfCharSet!=lf.lfCharSet)
_pE->setAttribute(L"CharSet",CComVariant(lf.lfCharSet));
if(!lfDef || lfDef->lfHeight!=lf.lfHeight)
_pE->setAttribute(L"Size",CComVariant(lf.lfHeight));
if(!lfDef || pDefStyle->Font_IsBold()!=sd.Font_IsBold())
_pE->setAttribute(L"Bold",CComVariant(sd.Font_IsBold()));
if(!lfDef || lfDef->lfStrikeOut!=lf.lfStrikeOut)
_pE->setAttribute(L"StrikeThrough",CComVariant(lf.lfStrikeOut));
if(!lfDef || lfDef->lfItalic!=lf.lfItalic)
_pE->setAttribute(L"Italic",CComVariant(lf.lfItalic?L"1":L"0"));
RemoveEmptyAttributeNode(pE,_pE);
}
{//Borders properties
CComPtr<MSXML2::IXMLDOMElement> _pE=CreateStyleNode(pXmlDoc,L"Borders",pE);
const Borders* pBdrs=sd.GetBorders();
if(pBdrs){
/*
const EXlLineStyle ls=pBdrs->bottom.get_LineStyle();
CComBSTR bstrLineStyle(EXlLineStyleToString(ls));
if(bstrLineStyle.Length()>0){
CComPtr<MSXML2::IXMLDOMElement> pBorderE;
pXmlDoc->createElement(L"Border",&pBorderE);
_pE->appendChild(pBorderE,NULL);
pBorderE->setAttribute(L"Position",CComVariant(L"Bottom"));
pBorderE->setAttribute(L"LineStyle",CComVariant(bstrLineStyle));
pBorderE->setAttribute(L"Weight",CComVariant(pBdrs->bottom.get_Weight()));
RemoveEmptyAttributeNode(_pE,pBorderE);
}
*/
CreateBorderNode(pXmlDoc,_pE,&pBdrs->bottom,L"Bottom");
CreateBorderNode(pXmlDoc,_pE,&pBdrs->left,L"Left");
CreateBorderNode(pXmlDoc,_pE,&pBdrs->right,L"Right");
CreateBorderNode(pXmlDoc,_pE,&pBdrs->top,L"Top");
}
RemoveEmptyChildNode(pE,_pE);
}
return S_OK;
}
HRESULT XmlMyCell::SaveStyles(Worksheet const* pGrid,map<StyleID_t,size_t>& mapStyleID,const RowHeader& rh,const ColHeader& ch,MSXML2::IXMLDOMDocument* pXmlDoc,MSXML2::IXMLDOMNode* pNode)
{
HRESULT hr=S_OK;
CComQIPtr<MSXML2::IXMLDOMElement> pE=pNode;
const StyleDesc& sd=pGrid->Style_GetTableStyle();
{
CComPtr<MSXML2::IXMLDOMNode> pN;
pE->selectSingleNode(L"Style[@ID=\"Default\"]",&pN);
CComQIPtr<MSXML2::IXMLDOMElement> _pE=pN;
if(_pE)
hr=_SaveStyles(sd,pXmlDoc,_pE);
}
vector<pair<StyleID_t,const StyleDesc*> > vec;
pGrid->Style_EnumStyles(vec);
//for(vector<pair<StyleID_t,StyleDesc> >::const_iterator it=vec.begin();it!=vec.end();++it){
for(size_t i=0;i<vec.size();++i){
const size_t nID=i+1;
//#pragma warning(disable:4267)
mapStyleID[vec[i].first]=nID;
//#pragma warning(default:4267)
AppendTextNode(pXmlDoc,pE,L"\r\n\t\t");
CComPtr<MSXML2::IXMLDOMElement> _pE;
pXmlDoc->createElement(L"Style",&_pE);
CString sid;sid.Format(_T("s%d"),nID);
_pE->setAttribute(L"ID",CComVariant(sid));
hr=_SaveStyles(vec[i].second,pXmlDoc,_pE,&sd);
pE->appendChild(_pE,NULL);
}
if(!vec.empty())
AppendTextNode(pXmlDoc,pE,L"\r\n\t");
return hr;
}
void XmlMyCell::CreateColumnNode(MSXML2::IXMLDOMDocument* pXmlDoc,bool& bCreated,int col,int nPreCol,MSXML2::IXMLDOMNode* pColumns,MSXML2::IXMLDOMElement** ppColE)
{
_ASSERT(NULL==*ppColE);
AppendTextNode(pXmlDoc,pColumns,L"\r\n\t\t");
//CComPtr<MSXML2::IXMLDOMElement> _pE;
pXmlDoc->createElement(L"c",ppColE);
bCreated=true;
pColumns->appendChild(*ppColE,NULL);
if(col && (-1==nPreCol || col-nPreCol>1)){
(*ppColE)->setAttribute(L"idx",CComVariant(col));
}
}
HRESULT XmlMyCell::SaveColumns(Worksheet const* pGrid,const RowHeader& rh,const ColHeader& ch,MSXML2::IXMLDOMDocument* pXmlDoc,MSXML2::IXMLDOMNode* pNode)
{
HRESULT hr=S_OK;
CComQIPtr<MSXML2::IXMLDOMElement> pE=pNode;
const int cols=ch.get_cols();
const int nDefWidth=ch.get_DefColWidth();
int nPreCol=-1;
TCHAR buf[MAX_CELLTEXT];
for(int col=0;col<cols;++col){
bool bCreated=false;
const int wi=ch.get_ColWidth(col);
CComPtr<MSXML2::IXMLDOMElement> _pE;
if(nDefWidth!=wi){
CreateColumnNode(pXmlDoc,bCreated,col,nPreCol,pE,&_pE);
_pE->setAttribute(L"wi",CComVariant(this->X_Pixel2Point(wi)));
}
const StyleID_t styleid=ch.Style_GetColStyleID(col);
if(styleid){
if(!_pE){
CreateColumnNode(pXmlDoc,bCreated,col,nPreCol,pE,&_pE);
}
CString sid;sid.Format(_T("s%d"),styleid);
_pE->setAttribute(L"sid",CComVariant(sid));
}
if(0){//����label
const int len=ch.get_text(col,buf);
if(len>0){
if(!_pE){
CreateColumnNode(pXmlDoc,bCreated,col,nPreCol,pE,&_pE);
}
_pE->setAttribute(L"l",CComVariant(buf));
}
}
if(bCreated){
nPreCol=col;
}
}
AppendTextNode(pXmlDoc,pE,L"\r\n\t");
return hr;
}
//struct xml_row_item
//{
// row_t row;
// short nRowHeight;
// vector<col_t> cells;
//};
void XmlMyCell::CreateRowNode(MSXML2::IXMLDOMDocument* pXmlDoc,int row,int nPreRow,bool& bRowCreated,MSXML2::IXMLDOMElement* pE,MSXML2::IXMLDOMElement** ppRowE)
{
AppendTextNode(pXmlDoc,pE,L"\r\n\t\t");
pXmlDoc->createElement(L"r",ppRowE);
pE->appendChild(*ppRowE,NULL);
bRowCreated=true;
if(row && (-1==nPreRow || row-nPreRow>1)){
(*ppRowE)->setAttribute(L"idx",CComVariant(row));
}
}
void XmlMyCell::CreateCellNode(MSXML2::IXMLDOMDocument* pXmlDoc,int row,int col,int nPreRow,int nPreCol,bool& bRowCreated,bool& bCellCreated,MSXML2::IXMLDOMElement* pE,CComPtr<MSXML2::IXMLDOMElement>& pRowE,CComPtr<MSXML2::IXMLDOMElement>& pCellE)
{
if(!pRowE){
CreateRowNode(pXmlDoc,row,nPreRow,bRowCreated,pE,&pRowE);
}
if(!pCellE){
AppendTextNode(pXmlDoc,pRowE,L"\r\n\t\t\t");
pXmlDoc->createElement(L"c",&pCellE);
pRowE->appendChild(pCellE,NULL);
bCellCreated=true;
if(nPreCol+1!=col){
pCellE->setAttribute(L"idx",CComVariant(col));
}
}
}
HRESULT XmlMyCell::SaveRows(Worksheet const* pGrid,const map<StyleID_t,size_t>& mapStyleID,const RowHeader& rh,const ColHeader& ch,MSXML2::IXMLDOMDocument* pXmlDoc,MSXML2::IXMLDOMNode* pNode)
{
HRESULT hr=S_OK;
CComQIPtr<MSXML2::IXMLDOMElement> pE=pNode;
const int nDefRowHeight=rh.get_DefRowHeight();
const int rows=rh.get_rows();
const int cols=ch.get_cols();
TCHAR buf[MAX_CELLTEXT];
int nPreRow=-1;
for(int row=0;row<rows;++row){
bool bRowCreated=false;
CComPtr<MSXML2::IXMLDOMElement> pRowE;
const int nRowHeight=rh.get_RowHeight(row);
if(nRowHeight!=nDefRowHeight){
CreateRowNode(pXmlDoc,row,nPreRow,bRowCreated,pE,&pRowE);
pRowE->setAttribute(L"hi",CComVariant(this->Y_Pixel2Point(nRowHeight)));
}
int nPreCol=-1;
for(int col=0;col<cols;++col){
const CellRange* pMerge=pGrid->GetMergeCells(row,col);
if(pMerge && !(pMerge->TopRow()==row && pMerge->LeftCol()==col))
continue;
bool bCellCreated=false;
CComPtr<MSXML2::IXMLDOMElement> pCellE;
//�������
//const StyleID_t nStyleID
const pair<StyleID_t,EStyleStorePosition> pr=pGrid->Style_GetCellStyleID(CellID(row,col));
if(ESP_STYLE_CELL_OWN==pr.second){
map<StyleID_t,size_t>::const_iterator it=mapStyleID.find(pr.first);
if(it!=mapStyleID.end()){
CreateCellNode(pXmlDoc,row,col,nPreRow,nPreCol,bRowCreated,bCellCreated,pE,pRowE,pCellE);
CString sid;sid.Format(_T("s%d"),it->second);
pCellE->setAttribute(L"sid",CComVariant(sid));
}
}
int nMergeAcross=0;
//��Ԫ��ϲ�����
if(pMerge && pMerge->TopRow()==row && pMerge->LeftCol()==col){
nMergeAcross=pMerge->RightCol()-col;
const int nMergeDown=pMerge->BottomRow()-row;
if(nMergeAcross||nMergeDown){
CreateCellNode(pXmlDoc,row,col,nPreRow,nPreCol,bRowCreated,bCellCreated,pE,pRowE,pCellE);
if(nMergeAcross)
pCellE->setAttribute(L"ma",CComVariant(nMergeAcross));
if(nMergeDown)
pCellE->setAttribute(L"md",CComVariant(nMergeDown));
}
}
//�ı�����
const int iTextLen= pGrid->GetCellText(row,col,buf);
if(iTextLen>0){
CreateCellNode(pXmlDoc,row,col,nPreRow,nPreCol,bRowCreated,bCellCreated,pE,pRowE,pCellE);
pCellE->setAttribute(L"t",CComVariant(buf));
}
//:~�ı�����
if(bCellCreated){
if(!nMergeAcross)
nPreCol=col;
else{
nPreCol=col+nMergeAcross;
}
}
}
if(bRowCreated)
nPreRow=row;
}
return hr;
}
//HRESULT SaveMergeCells(Worksheet const* pGrid,const RowHeader& rh,const ColHeader& ch,MSXML2::IXMLDOMNode* pNode)
//{
// HRESULT hr=S_OK;
// CComQIPtr<MSXML2::IXMLDOMElement> pE=pNode;
// return hr;
//}
HRESULT XmlMyCell::save(Worksheet const* pGrid,LPCTSTR lpszFile)
{
HRESULT hr=S_OK;
CComPtr<MSXML2::IXMLDOMDocument> pXmlDoc;
if FAILED(hr=pXmlDoc.CoCreateInstance(MSXML2::CLSID_DOMDocument))
return hr;
if FAILED(hr=init(pXmlDoc))
return hr;
const RowHeader& rh=pGrid->get_RowHeader();
const ColHeader& ch=pGrid->get_ColHeader();
CComPtr<MSXML2::IXMLDOMNode> pN;
{
//rh.get_FreezeBottomRow
pXmlDoc->selectSingleNode(L"/mycell/GridProperties",&pN);
CComQIPtr<MSXML2::IXMLDOMElement> pE=pN;
pE->setAttribute(L"Rows",CComVariant(rh.get_rows()));
pE->setAttribute(L"Cols",CComVariant(ch.get_cols()));
pE->setAttribute(L"DefaultColumnWidth",CComVariant(X_Pixel2Point(ch.get_DefColWidth())));
pE->setAttribute(L"DefaultRowHeight",CComVariant(this->Y_Pixel2Point(rh.get_DefRowHeight())));
}
for(int i=0;i<1;++i){
pN.Release();
hr=pXmlDoc->selectSingleNode(L"/mycell/Styles",&pN);
if(!pN)
break;
map<StyleID_t,size_t> mapStyleID;
SaveStyles(pGrid,mapStyleID,rh,ch,pXmlDoc,pN);
pN.Release();
pXmlDoc->selectSingleNode(L"/mycell/Columns",&pN);
SaveColumns(pGrid,rh,ch,pXmlDoc,pN);
pN.Release();
pXmlDoc->selectSingleNode(L"/mycell/Rows",&pN);
SaveRows(pGrid,mapStyleID,rh,ch,pXmlDoc,pN);
//pN.Release();
//pXmlDoc->selectSingleNode(L"/mycell/MergeCells",&pN);
//SaveMergeCells(pGrid,rh,ch,pN);
}
//pXmlDoc->save(CComVariant(lpszFile));
if FAILED(hr=pXmlDoc->save(CComVariant(lpszFile)))
return hr;
return hr;
}
HRESULT XmlMyCell::init(MSXML2::IXMLDOMDocument* pXmlDoc)
{
CComBSTR xml(L"<?xml version=\"1.0\"?>");
xml.Append(L"<mycell>\r\n");
xml.Append(L"<!--ӳ���ϵ(sid->StyleID),(idx->Index),(r->row),(c->column),(hi->Height),(wi->Width),(t->text),(ma->MergeAcross),(md->MergeDown),(l->Label)-->\r\n");
xml.Append(L"<DocumentProperties><Author>yanxm</Author><Version>1.0</Version></DocumentProperties>\r\n");
xml.Append(L"<GridProperties/>\r\n");
xml.Append(L"<Styles>\r\n\t<Style ID=\"Default\" Name=\"Normal\"/>\r\n</Styles>\r\n");
xml.Append(L"<Columns/>\r\n");
xml.Append(L"<Rows/>\r\n");
xml.Append(L"</mycell>");
VARIANT_BOOL bOk;
HRESULT hr=pXmlDoc->loadXML(xml,&bOk);
return hr;
}
}//namespace mycell