www.gusucode.com > VC++启程报表DHTML表格显示-源码程序 > VC++启程报表DHTML表格显示-源码程序/code/SHTMLReport.cpp
//Download by http://www.NewXing.com // SHTMLReport.cpp: implementation of the CSHTMLReport class. // 模块:启程报表(基于DHTML) // 说明:采用HTML提供对表格形式的数据的显示,目前只提供了几个常用的接口, // 接口: // void SetIndexFormat(CString strIndexFormat); // BOOL MergeCol(int iCol); // BOOL MergeRow(int iRow); // BOOL DeleteRow(int index); // BOOL SetItemHTML(int iRow,int iCol,CString html); // BOOL InsertRow(int index); // void SetTableName(CString name); // void SetHtmlDocPtr(IHTMLDocument2 *pDoc); // 本代码可以任意使用、修改、传播。 // 黄建雄 2003-10-14 // huangjianxiong@sina.com ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "sreport.h" #include "SHTMLReport.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSHTMLReport::CSHTMLReport() { m_pHtmlDoc2=NULL; m_iHeadLines=1; } CSHTMLReport::~CSHTMLReport() { } //*********************************************** // 指定HTML文档接口 //********************************************** void CSHTMLReport::SetHtmlDocPtr(IHTMLDocument2 *pDoc) { m_pHtmlDoc2=pDoc; } //*********************************************** // 指定操作的表的名称,表名称在HTML模板中指定 //********************************************* void CSHTMLReport::SetTableName(CString name) { m_strTableName=name; } //************************************************** // 获取HTML表格COM接口,内部接口 //************************************************** IHTMLTable * CSHTMLReport::GetTableDispatch() { ASSERT(m_pHtmlDoc2); IHTMLElementCollection *all; m_pHtmlDoc2->get_all(&all); IDispatch *distable; all->item(COleVariant(m_strTableName),COleVariant(short(0)),&distable); IHTMLTable *pITable=NULL; HRESULT hr=distable->QueryInterface(IID_IHTMLTable, (void**)&pITable);//get table dispatch ASSERT(hr==S_OK); return pITable; } //******************************************************* // 在指定位置插入一行,index==-1表示append //******************************************************* BOOL CSHTMLReport::InsertRow(int index) { IHTMLTable *pITable=GetTableDispatch(); IDispatch *disrow; HRESULT hr=pITable->insertRow(index,&disrow);//insert a row at 1 position if(hr!=S_OK) return FALSE; IHTMLTableRow *pIRow; hr=disrow->QueryInterface(IID_IHTMLTableRow, (void**)&pIRow); ASSERT(hr==S_OK); long cols; hr=pITable->get_cols(&cols); ASSERT(hr==S_OK&&cols!=0); IDispatch *discell; IHTMLElement *cell; CString str= " "; BSTR bsStr = str.AllocSysString(); for(int i=0;i<cols;i++) { pIRow->insertCell(i,&discell); discell->QueryInterface(IID_IHTMLElement,(void **)&cell); cell->put_innerHTML(bsStr); cell->Release(); discell->Release(); } SysFreeString(bsStr); pIRow->Release(); if(!m_strIndexFormat.IsEmpty()) { IHTMLElementCollection *irows; hr=pITable->get_rows(&irows); ASSERT(hr==S_OK); long rows; hr=irows->get_length(&rows); ASSERT(hr==S_OK); CString strHead=""; if(index==-1) index=rows-1; for(long i=index;i<rows;i++) { strHead.Format(m_strIndexFormat,i); BSTR bsStrHead=strHead.AllocSysString(); hr=irows->item(COleVariant(long(i)),COleVariant(long(0)),&disrow); ASSERT(hr==S_OK); //get row interface hr=disrow->QueryInterface(IID_IHTMLTableRow, (void**)&pIRow); ASSERT(hr==S_OK); IHTMLElementCollection *icells; hr=pIRow->get_cells(&icells); ASSERT(hr==S_OK); hr=icells->item(COleVariant(long(0)),COleVariant(long(0)),&discell); ASSERT(hr==S_OK); discell->QueryInterface(IID_IHTMLElement,(void **)&cell); ASSERT(hr==S_OK); cell->put_innerText(bsStrHead); SysFreeString(bsStrHead); cell->Release(); pIRow->Release(); disrow->Release(); } irows->Release(); } pIRow->Release(); disrow->Release(); pITable->Release(); return TRUE; } //*************************************************************** // 修改单元格的内容:可以使用html语法 //*************************************************************** BOOL CSHTMLReport::SetItemHTML(int iRow, int iCol, CString html) { IHTMLTable *pITable=GetTableDispatch(); //get row collect IHTMLElementCollection *pIRows; HRESULT hr=pITable->get_rows(&pIRows); ASSERT(hr==S_OK); //get specisfied row IDispatch *disrow; hr=pIRows->item(COleVariant(long(iRow)),COleVariant(short(0)),&disrow);//iRow row if(hr!=S_OK||disrow==NULL) return FALSE; IHTMLTableRow *pIRow; hr=disrow->QueryInterface(IID_IHTMLTableRow, (void**)&pIRow); ASSERT(hr==S_OK); //get cell collect IHTMLElementCollection *rowcells; pIRow->get_cells(&rowcells); //get cell IDispatch *discell; IHTMLElement *cell; hr=rowcells->item(COleVariant(long(iCol)),COleVariant(short(0)),&discell);//iCol col if(hr!=S_OK||discell==NULL) return FALSE; hr=discell->QueryInterface(IID_IHTMLElement,(void **)&cell); ASSERT(hr==S_OK); BSTR bsStr = html.AllocSysString(); cell->put_innerHTML(bsStr); SysFreeString(bsStr); cell->Release(); pIRow->Release(); pITable->Release(); return TRUE; } //************************************************ // 删除指定行 //************************************************ BOOL CSHTMLReport::DeleteRow(int index) { IHTMLTable *pITable=GetTableDispatch(); HRESULT hr=pITable->deleteRow(index); pITable->Release(); return hr==S_OK; } //************************************************ // 将指定行数据相同的单元格合并 //************************************************ BOOL CSHTMLReport::MergeRow(int iRow) { IHTMLTable *pITable=GetTableDispatch(); //get row collect IHTMLElementCollection *pIRows; HRESULT hr=pITable->get_rows(&pIRows); ASSERT(hr==S_OK); //get specisfied row IDispatch *disrow; hr=pIRows->item(COleVariant(long(iRow)),COleVariant(short(0)),&disrow);//iRow row if(hr!=S_OK||disrow==NULL) return FALSE; IHTMLTableRow *pIRow; hr=disrow->QueryInterface(IID_IHTMLTableRow, (void**)&pIRow); ASSERT(hr==S_OK); //get cell collect IHTMLElementCollection *rowcells; pIRow->get_cells(&rowcells); long cells; hr=rowcells->get_length(&cells); IDispatch *discell; IHTMLElement *icellElement; long begin=-1,end=-1; CString beginStr; CString cellStr; long beginRowSpan=0,rowSpan; for(long i=m_strIndexFormat.IsEmpty()?0:1;i<cells;i++) { //get cell hr=rowcells->item(COleVariant(long(i)),COleVariant(short(0)),&discell); ASSERT(hr==S_OK&&discell!=NULL); hr=discell->QueryInterface(IID_IHTMLElement,(void **)&icellElement); ASSERT(hr==S_OK&&icellElement!=NULL); cellStr=GetElementText(icellElement,inner_text); IHTMLTableCell *icell; hr=discell->QueryInterface(IID_IHTMLTableCell,(void **)&icell); ASSERT(hr==S_OK&&icell!=NULL); icell->get_rowSpan(&rowSpan); if(cellStr!=beginStr||rowSpan!=beginRowSpan) { if(end-begin+1>1&&begin!=-1) { ASSERT(beginRowSpan!=0); MergeRowPrivate(pIRow,begin,end); cells-=end-begin; i-=end-begin; } begin=end=i; beginStr=cellStr; beginRowSpan=rowSpan; }else end=i; icell->Release(); icellElement->Release(); } if(begin!=end) MergeRowPrivate(pIRow,begin,end); pIRow->Release(); pITable->Release(); return TRUE; } //************************************************ // 将指定列数据相同的单元格合并 //************************************************ BOOL CSHTMLReport::MergeCol(int iCol) { IHTMLTable *pITable=GetTableDispatch(); //get row collect IHTMLElementCollection *pIRows; HRESULT hr=pITable->get_rows(&pIRows); ASSERT(hr==S_OK); CSArray<COLCELLINFO> colArray; if(!MakeColDispatchCollection(pIRows,iCol,colArray)) return FALSE; int colCells=colArray.GetSize(); COLCELLINFO cci; CString beginStr,cellStr; long beginColSpan=0,colSpan; int begin=-1,end; for(int i=0;i<colCells;i++) { cci=colArray.GetAt(i); if(cci.pDisCell==NULL) continue; IHTMLElement *icellElement; hr=cci.pDisCell->QueryInterface(IID_IHTMLElement,(void **)&icellElement); ASSERT(hr==S_OK&&icellElement!=NULL); cellStr=GetElementText(icellElement,inner_text); IHTMLTableCell *icell; hr=cci.pDisCell->QueryInterface(IID_IHTMLTableCell,(void **)&icell); ASSERT(hr==S_OK&&icell!=NULL); hr=icell->get_colSpan(&colSpan); if(cellStr!=beginStr||colSpan!=beginColSpan) { if(begin!=-1&&end-begin+1>1) { ASSERT(beginColSpan!=0); MergeColPrivate(pIRows,colArray,begin,end); } begin=end=i; beginStr=cellStr; beginColSpan=colSpan; }else end=i; icell->Release(); icellElement->Release(); } if(begin!=end) MergeColPrivate(pIRows,colArray,begin,end); pITable->Release(); return TRUE; } //*********************************************** // 设置索引列的显示格式:遵循sprintf函数的规则 //*********************************************** void CSHTMLReport::SetIndexFormat(CString strIndexFormat) { m_strIndexFormat=strIndexFormat; } //************************************************* // 获取元素的字符 //************************************************* CString CSHTMLReport::GetElementText(IHTMLElement *pElement, int type) { CString str= ""; BSTR bsStr = str.AllocSysString(); switch(type) { case inner_text: pElement->get_innerText(&bsStr); break; case inner_html: pElement->get_innerHTML(&bsStr); break; case outer_text: pElement->get_outerText(&bsStr); break; case outer_html: pElement->get_outerHTML(&bsStr); break; default: ASSERT(0); break; } _bstr_t bstStr; bstStr = bsStr; str.Format("%s",(LPCTSTR)bstStr); SysFreeString(bsStr); return str; } //******************************************************** // 设置元素字符 //******************************************************* BOOL CSHTMLReport::SetElementText(IHTMLElement *pElement, int type,CString str) { BSTR bsStr = str.AllocSysString(); HRESULT hr; switch(type) { case inner_text: hr=pElement->put_innerText(bsStr); break; case inner_html: hr=pElement->put_innerHTML(bsStr); break; case outer_text: hr=pElement->put_outerText(bsStr); break; case outer_html: hr=pElement->put_outerHTML(bsStr); break; default: ASSERT(0); break; } SysFreeString(bsStr); return (hr==S_OK); } //****************************************************************** // 在指定的行中从指定的起始及终止位置进行合并:内部函数 //****************************************************************** void CSHTMLReport::MergeRowPrivate(IHTMLTableRow *pIRow, long begincol, long endcol) { long colSpan=0; IHTMLElementCollection *picells; HRESULT hr=pIRow->get_cells(&picells); for(long i=endcol;i>=begincol;i--) { IDispatch *discell; hr=picells->item(COleVariant(i),COleVariant(short(0)),&discell); ASSERT(hr==S_OK&&discell!=NULL); IHTMLTableCell *picell; hr=discell->QueryInterface(IID_IHTMLTableCell,(void **)&picell); ASSERT(hr==S_OK&&picell!=NULL); long tmpColSpan; picell->get_colSpan(&tmpColSpan); colSpan+=tmpColSpan; if(i==begincol) picell->put_colSpan(colSpan); else pIRow->deleteCell(i); picell->Release(); } } //****************************************************************** // 在指定的行集中对指定列从指定的起始及终止位置进行合并:内部函数 //****************************************************************** void CSHTMLReport::MergeColPrivate(IHTMLElementCollection *pIRowArray,CSArray<COLCELLINFO> &colArray,long beginrow, long endrow) { IHTMLTableCell *ibegincell=NULL; long rowSpan=0; for(int i=beginrow;i<=endrow;i++) { IHTMLTableCell *icell; COLCELLINFO cci=colArray.GetAt(i); ASSERT(cci.iIndexInRow!=-1); IDispatch *disrow; HRESULT hr=pIRowArray->item(COleVariant(cci.iRow),COleVariant(short(0)),&disrow);//iRow row if(hr!=S_OK||disrow==NULL) return ; IHTMLTableRow *pIRow; hr=disrow->QueryInterface(IID_IHTMLTableRow, (void**)&pIRow); ASSERT(hr==S_OK); //get cell collection IHTMLElementCollection *rowcells; pIRow->get_cells(&rowcells); //get cell element IDispatch *discell; hr=rowcells->item(COleVariant(cci.iIndexInRow),COleVariant(short(0)),&discell); ASSERT(hr==S_OK&&discell!=NULL); hr=discell->QueryInterface(IID_IHTMLTableCell,(void **)&icell); ASSERT(hr==S_OK&&icell!=NULL); long tmpRowSpan; hr=icell->get_rowSpan(&tmpRowSpan); ASSERT(hr==S_OK); rowSpan+=tmpRowSpan; if(i==beginrow) { ibegincell=icell; }else{ icell->Release(); if(cci.iIndexInRow!=-1) pIRow->deleteCell(cci.iIndexInRow); } pIRow->Release(); } ibegincell->put_rowSpan(rowSpan); ibegincell->Release(); } //****************************************************************** // 构造指定列的集合:内部函数 //****************************************************************** BOOL CSHTMLReport::MakeColDispatchCollection( IHTMLElementCollection *pIRowArray/*in*/, long iCol/*in*/, CSArray<COLCELLINFO> &colArray/*out*/) { long rows; HRESULT hr=pIRowArray->get_length(&rows); ASSERT(hr==S_OK); IHTMLElementCollection **rowcellsarray =new IHTMLElementCollection *[rows]; //get cell collect array for(int j=0;j<rows;j++) { //get specisfied row IDispatch *disrow; hr=pIRowArray->item(COleVariant(long(j)),COleVariant(short(0)),&disrow);//iRow row if(hr!=S_OK||disrow==NULL) return FALSE; IHTMLTableRow *pIRow; hr=disrow->QueryInterface(IID_IHTMLTableRow, (void**)&pIRow); ASSERT(hr==S_OK); //get cell collection pIRow->get_cells(&rowcellsarray[j]); pIRow->Release(); } struct colindexinfo{ long index; //在行中的索引 long iCol; //在列中的索引 long colSpan;//列跨越 }; struct colindexinfo *ciis=new struct colindexinfo[rows]; memset(ciis,0,rows*sizeof(struct colindexinfo)); for(j=1;j<=iCol;j++)//追踪到第iCol列:初始化的数据即为第一列的数据,不需要计算 { for(int k=0;k<rows;k++) { if(ciis[k].iCol+ciis[k].colSpan>j) continue; IDispatch *discell; hr=rowcellsarray[k]->item(COleVariant(ciis[k].index),COleVariant(short(0)),&discell); ASSERT(hr==S_OK&&discell!=NULL); IHTMLTableCell *icell; hr=discell->QueryInterface(IID_IHTMLTableCell,(void **)&icell); ASSERT(hr==S_OK&&icell!=NULL); long colSpan,rowSpan; hr=icell->get_colSpan(&colSpan); ASSERT(hr==S_OK); hr=icell->get_rowSpan(&rowSpan); icell->Release(); ciis[k].index++; ciis[k].iCol+=colSpan; ciis[k].colSpan=colSpan-1; for(int kk=k+1;kk<k+rowSpan;kk++) { if(ciis[kk].iCol+ciis[kk].colSpan>j){ delete []ciis; delete []rowcellsarray; return FALSE; } ciis[kk].iCol++; ciis[kk].colSpan=0; } k+=rowSpan-1; } } for(int i=0;i<rows;i++) { if(ciis[i].colSpan){ COLCELLINFO cci={i,NULL,-1}; colArray.Add(cci); continue; } IDispatch *discell; hr=rowcellsarray[i]->item(COleVariant(ciis[i].index),COleVariant(short(0)),&discell); ASSERT(hr==S_OK&&discell!=NULL); IHTMLTableCell *icell; hr=discell->QueryInterface(IID_IHTMLTableCell,(void **)&icell); ASSERT(hr==S_OK&&icell!=NULL); long rowSpan; hr=icell->get_rowSpan(&rowSpan); icell->Release(); COLCELLINFO cci; cci.iRow=i; cci.iIndexInRow=ciis[i].index; cci.pDisCell=discell; colArray.Add(cci); i+=rowSpan-1; } delete []ciis; delete []rowcellsarray; return TRUE; }