313 lines
7.6 KiB
C++
313 lines
7.6 KiB
C++
#include "stdafx.h"
|
|
#include "ExcelWrite.h"
|
|
#include "excel9.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[]=__FILE__;
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
CExcelWrite::CExcelWrite()
|
|
{
|
|
}
|
|
|
|
CExcelWrite::~CExcelWrite()
|
|
{
|
|
}
|
|
|
|
BOOL CExcelWrite::ExcelWrite(CListCtrl* pListCtrl, LPCTSTR pszIniDefFile, BOOL bOpen)
|
|
{
|
|
if (NULL == pListCtrl || NULL == pszIniDefFile)
|
|
return FALSE;
|
|
|
|
//1.读取xls文件定义名
|
|
CString sReportFile = pszIniDefFile;
|
|
sReportFile.MakeLower();
|
|
sReportFile.Replace(_T(".ini"),_T(".xls"));
|
|
|
|
/*::GetPrivateProfileString(_T("File"), _T("Templ"), _T(""), sReportFile.GetBuffer(MAX_PATH), MAX_PATH, pszIniDefFile);
|
|
sReportFile.ReleaseBuffer();
|
|
sReportFile.Replace(_T('/'), _T('\\'));
|
|
|
|
// 确定xls文件名
|
|
if (sReportFile.IsEmpty())
|
|
{
|
|
LPCTSTR pszSub = _tcsrchr(pszIniDefFile, _T('\\')) + 1;
|
|
sReportFile = pszSub;
|
|
int iFind = sReportFile.ReverseFind(_T('.'));
|
|
if (iFind > 0) sReportFile.Delete(iFind, 4);
|
|
sReportFile += _T(".xls");
|
|
}
|
|
// 确定xls文件位置
|
|
if (sReportFile.ReverseFind(_T('\\')) < 0)
|
|
{
|
|
TCHAR szPathName[MAX_PATH];
|
|
::GetModuleFileName(NULL, szPathName, MAX_PATH);
|
|
LPTSTR pszSub = _tcsrchr(szPathName, _T('\\'));
|
|
ASSERT(NULL != pszSub); pszSub[1] = _T('\0');
|
|
_tcscat(szPathName, _T("Report\\"));
|
|
sReportFile.Insert(0, szPathName);
|
|
}*/
|
|
|
|
//2.行定义
|
|
int nRowFrom = ::GetPrivateProfileInt(_T("Row"),_T("RowFrom"),-1,pszIniDefFile);
|
|
int nRowTo = ::GetPrivateProfileInt(_T("Row"),_T("RowTo"),-1,pszIniDefFile);
|
|
if (nRowFrom == -1 )
|
|
{
|
|
AfxMessageBox(_T("配置文件的定义信息不完整!请检查配置文件!"));
|
|
return FALSE;
|
|
}
|
|
|
|
TCHAR szResult[_MAX_PATH];
|
|
::GetPrivateProfileString(_T("Row"),_T("Cells"),_T("Null"),szResult,_MAX_PATH,pszIniDefFile);
|
|
if (_tcscmp(szResult,_T("Null")) == 0)
|
|
{
|
|
AfxMessageBox(_T("配置文件的定义信息不完整!请检查配置文件!"));
|
|
return FALSE;
|
|
}
|
|
|
|
CStringArray arCells;
|
|
ScriptToCells(szResult,arCells);
|
|
|
|
//3. 依次读取cell对应的listCtrl名称
|
|
CMapStringToString mapCellToCols;
|
|
CString sCell,sCellScr;
|
|
for (int i = 0;i < arCells.GetSize();i++)
|
|
{
|
|
sCell = arCells.GetAt(i);
|
|
::GetPrivateProfileString(_T("Cell"),sCell,_T("Null"),szResult,_MAX_PATH,pszIniDefFile);
|
|
|
|
if (_tcscmp(szResult,_T("Null")) != 0)
|
|
{
|
|
//一个单元格可能和多个列脚本有关
|
|
sCellScr = szResult;
|
|
sCellScr.TrimLeft();
|
|
sCellScr.TrimRight();
|
|
mapCellToCols.SetAt(sCell,sCellScr);
|
|
}
|
|
}
|
|
|
|
//4. 开始写文件
|
|
return ImpWriteExcel(nRowFrom,nRowTo,sReportFile,mapCellToCols,pListCtrl,bOpen);
|
|
}
|
|
|
|
BOOL CExcelWrite::ImpWriteExcel(int nRowFrom,int nRowTo,CString& sXlsTmplFile,
|
|
CMapStringToString& mapCellToCols,CListCtrl* pListCtrl,BOOL bOpen)
|
|
{
|
|
ASSERT(pListCtrl != NULL);
|
|
::CoInitialize(NULL);
|
|
|
|
_Application excelApp;
|
|
Workbooks excelBooks;
|
|
_Workbook excelBook;
|
|
Worksheets excelSheets;
|
|
_Worksheet excelSheet;
|
|
|
|
COleVariant vResult;
|
|
COleVariant covTrue((short)TRUE),covFalse((short)FALSE);
|
|
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
|
|
|
|
Range range;
|
|
Range iCell;
|
|
|
|
BOOL bSuccess = excelApp.CreateDispatch(_T("excel.application"));
|
|
if (bSuccess)
|
|
{
|
|
LPDISPATCH pLpDisp = NULL;
|
|
|
|
excelBooks.AttachDispatch(excelApp.GetWorkbooks());
|
|
pLpDisp = excelBooks.Open( sXlsTmplFile,covOptional,covOptional,covOptional,
|
|
covOptional,covOptional,covOptional,covOptional,
|
|
covOptional,covOptional,covOptional,covOptional,
|
|
covOptional);
|
|
if (pLpDisp == NULL)
|
|
{
|
|
AfxMessageBox(_T("启动excel 服务失败!请确认系统是否安装Excel!"));
|
|
return FALSE;
|
|
}
|
|
|
|
excelBook.AttachDispatch(pLpDisp);
|
|
|
|
//得到Worksheets
|
|
excelSheets.AttachDispatch(excelBook.GetWorksheets());
|
|
|
|
//获取sheet 数量
|
|
long lCount = excelSheets.GetCount();
|
|
|
|
//从第一模板sheet开始
|
|
short nSheetIndex = 1;
|
|
COleVariant varIndex(nSheetIndex);
|
|
pLpDisp = excelSheets.GetItem(varIndex);
|
|
if (pLpDisp != NULL)
|
|
{
|
|
excelSheet.AttachDispatch(pLpDisp);
|
|
CString sCellIndex,sCols,sValue,sCell;
|
|
|
|
//遍历所有的明细行数据
|
|
int nRowIndex = 0;
|
|
for (int i = 0;i < pListCtrl->GetItemCount();i++)
|
|
{
|
|
for (POSITION ps = mapCellToCols.GetStartPosition();ps != NULL;)
|
|
{
|
|
mapCellToCols.GetNextAssoc(ps,sCellIndex,sCols);
|
|
|
|
//根据Cols 合成该行数据文本
|
|
sValue = _T("");
|
|
FormatColsValue(pListCtrl,i,sCols,sValue);
|
|
|
|
sCell.Format(_T("%s%d"),sCellIndex,nRowFrom + nRowIndex);
|
|
|
|
COleVariant varCell(sCell);
|
|
range = excelSheet.GetRange(varCell,varCell);
|
|
|
|
COleVariant varText(sValue);
|
|
range.SetValue(varText);
|
|
}
|
|
|
|
nRowIndex += 1;
|
|
if (nRowTo != -1 && nRowTo > nRowFrom)//有要求分页的情况
|
|
{
|
|
if ((nRowFrom + nRowIndex) > nRowTo)
|
|
{
|
|
nSheetIndex = (nRowFrom + i) / (nRowTo - nRowFrom) + ( (nRowFrom + i) % (nRowTo - nRowFrom) ? 1 : 0);
|
|
if (varIndex.iVal != nSheetIndex)
|
|
{
|
|
if (nSheetIndex >= lCount)
|
|
{
|
|
AfxMessageBox(_T("模板文件Sheet数量不够,明细部分数据没有导出,请增加模板Sheet后再导出!"));
|
|
break;
|
|
}
|
|
|
|
varIndex.iVal = nSheetIndex;
|
|
pLpDisp = excelSheets.GetItem(varIndex);
|
|
if (pLpDisp != NULL)
|
|
{
|
|
nRowIndex = 0;
|
|
excelSheet.AttachDispatch(pLpDisp);
|
|
}
|
|
else
|
|
{
|
|
AfxMessageBox(_T("获取第%d模板Sheet失败,明细部分数据没有导出,请检查模板Excel文件!"));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//年月 日 分 秒 文件记录
|
|
CString sAdd;
|
|
CString sSaveAsFileName = sXlsTmplFile;
|
|
CTime tNow = CTime::GetCurrentTime();
|
|
sAdd = tNow.Format(" %Y-%m-%d %H.%M.%S");
|
|
sAdd += _T(".xls");
|
|
sSaveAsFileName.Replace(_T(".xls"),sAdd);
|
|
|
|
//另外保存新文件
|
|
COleVariant varNewEFile(sSaveAsFileName);
|
|
excelBook.SaveAs(varNewEFile,covOptional,covOptional,covOptional,
|
|
covOptional,covOptional,0,covOptional,covOptional,
|
|
covOptional,covOptional);
|
|
|
|
excelBooks.Close();
|
|
excelApp.Quit();
|
|
if (bOpen)
|
|
{
|
|
ShellExecute(AfxGetMainWnd()->m_hWnd,_T("open"),sSaveAsFileName,_T(""),_T(""),SW_SHOWNORMAL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
::CoUninitialize();
|
|
AfxMessageBox(_T("创建xls失败! 报表到xls文件需要本机安装Microsoft excel 软件!"));
|
|
return FALSE;
|
|
}
|
|
::CoUninitialize();
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CExcelWrite::FormatColsValue(CListCtrl* pListCtrl,int nItem,CString& sCols,CString& sValue)
|
|
{
|
|
sValue = sCols;
|
|
HDITEM hdi;
|
|
TCHAR lpBuffer[_MAX_PATH];
|
|
memset(lpBuffer,0,_MAX_PATH);
|
|
|
|
hdi.mask = HDI_TEXT;
|
|
hdi.pszText = lpBuffer;
|
|
hdi.cchTextMax = _MAX_PATH;
|
|
|
|
CString sText,sTextAll = _T(""),sValueBk = sValue;
|
|
int nCount = pListCtrl->GetHeaderCtrl()->GetItemCount();
|
|
for (int i = 0;i < nCount;i++)
|
|
{
|
|
pListCtrl->GetHeaderCtrl()->GetItem(i,&hdi);
|
|
|
|
//找到listctrl的列名称
|
|
if (sCols.Find(hdi.pszText,0) != -1)
|
|
{
|
|
sText = pListCtrl->GetItemText(nItem,i);
|
|
sTextAll += sText;
|
|
|
|
sValue.Replace(hdi.pszText,sText);
|
|
}
|
|
}
|
|
sTextAll.TrimLeft();
|
|
sTextAll.TrimRight();
|
|
if (sTextAll.IsEmpty())
|
|
{
|
|
sValue = _T("");
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CExcelWrite::ScriptToCells(LPCTSTR pszScript,CStringArray& arCells)
|
|
{
|
|
CString sScript = pszScript;
|
|
sScript.TrimLeft();
|
|
sScript.TrimRight();
|
|
int nIndex = -1;
|
|
CString sCell;
|
|
|
|
while(TRUE)
|
|
{
|
|
sScript.TrimLeft();
|
|
sScript.TrimRight();
|
|
|
|
nIndex = sScript.Find(_T(","),0);
|
|
if (nIndex != -1)
|
|
{
|
|
sCell = sScript.Mid(0,nIndex);
|
|
//去掉空格
|
|
sCell.TrimLeft();
|
|
sCell.TrimRight();
|
|
arCells.Add(sCell);
|
|
|
|
if (nIndex + 1 < sScript.GetLength())
|
|
{
|
|
sCell = sScript.Mid(nIndex + 1);
|
|
|
|
//去掉空格
|
|
sCell.TrimLeft();
|
|
sCell.TrimRight();
|
|
sScript = sCell;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sScript.GetLength() > 0)
|
|
{
|
|
arCells.Add(sCell);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return arCells.GetSize() > 0;
|
|
}
|