Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

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;
}