在 VS 環境下開發 C++ 程序自動化操作 PowerPoint,支持基於模板修改文本框、圖表、表格,滿足軟件自動生成 PPT 報告需求。核心思路:先手工制作 PPT 模板,程序中通過 COM 接口修改模板數據並另存。
在 VS2012 中通過「類向導」添加 MFC 類,選擇「從類型庫添加類」。
選擇「Microsoft PowerPoint 14.0 Object Library」(版本號視 Office 版本而定),勾選所需接口生成包裝類。
由於 PPT 圖表數據底層由 Excel 存儲,修改圖表數據需同時生成 Excel COM 接口包裝類。
class CPPTObject {
public:
CApplication m_PPTApp; // PPT 應用程序對象
CSlides m_Slides; // 幻燈片集合
CSlide m_curSlide; // 當前操作幻燈片
CPresentation m_Presentaion; // 演示文稿對象
};
bool CPPTUtil::CreatePPTApplication() {
COleException exception;
LPCSTR str = "Powerpoint.Application";
if (!m_pPPTObject->m_PPTApp.CreateDispatch(str, &exception)) {
AfxMessageBox(exception.m_strError, MB_SETFOREGROUND);
return false;
}
m_pPPTObject->m_PPTApp.put_Visible(true); // 可見模式便於調試
return true;
}
bool CPPTUtil::OpenPPT(const std::string& pptPath) {
CPresentations presentations = m_pPPTObject->m_PPTApp.get_Presentations();
m_pPPTObject->m_Presentaion = presentations.Open(
CString(pptPath.c_str()), 0, 0, 1); // 只讀打開
m_pPPTObject->m_Slides = m_pPPTObject->m_Presentaion.get_Slides();
return true;
}
bool CPPTUtil::ClosePPT() {
m_pPPTObject->m_Presentaion.Save();
m_pPPTObject->m_Presentaion.Close();
m_pPPTObject->m_PPTApp.Quit();
return true;
}
bool CPPTUtil::SelectSlide(long slideIndex) {
if (slideIndex > m_pPPTObject->m_Slides.get_Count()) return false;
m_pPPTObject->m_curSlide = m_pPPTObject->m_Slides.Range(COleVariant(slideIndex));
return true;
}
bool CPPTUtil::ModifyTextBox(const std::string& boxName, const std::string& strValue) {
CShapes shapes = m_pPPTObject->m_curSlide.get_Shapes();
for (long i = 1; i <= shapes.get_Count(); ++i) {
CShape shape(shapes.Item(COleVariant(i)));
CString name = shape.get_Name();
if (shape.get_Type() == (long)Office::msoTextBox &&
name.Compare(CString(boxName.c_str())) == 0) {
CTextFrame textFrame = shape.get_TextFrame();
CTextRange textRange = textFrame.get_TextRange();
textRange.put_Text(strValue.c_str());
}
}
return true;
}
注意:Shape Name 在 PowerPoint 界面不可見,需通過調試獲取。
圖表數據實際存儲於內嵌 Excel 工作表中,需定義單元格與圖表數據結構:
// 單元格數據
class CCellDataCom {
CellValueType m_ValueType; // 類型:字符串/整數/浮點
std::string m_strValue;
std::string m_strPos; // 如 "A1", "B2"
// ... 構造函數、GetValue、GetPos、indexToString 等方法
};
// 圖表數據(多行多列)
class CChartDataCom {
std::list<std::list<CCellDataCom>> m_lstValue;
void insertRowData(const std::list<CCellDataCom>& row);
const std::list<std::list<CCellDataCom>>& getValue() const;
};
ChartData,獲取內嵌 Workbook 及第一個 Worksheet。ModifyCellData 逐單元格寫入值。app0.Quit()),並適當 Sleep 確保釋放資源。bool CPPTUtil::ModifyCellData(CWorksheet sheet, CCellDataCom cellData) {
const std::string& cellPos = cellData.getPos();
CRange range = sheet.get_Range(COleVariant(cellPos.c_str()), COleVariant(cellPos.c_str()));
COleVariant* pOleVar = nullptr;
switch (cellData.getValueType()) {
case CELL_STRING_TYPE: pOleVar = new COleVariant(CString(cellData.getStringValue().c_str())); break;
case CELL_LONG_TYPE: pOleVar = new COleVariant(cellData.getLongValue()); break;
case CELL_DOUBLE_TYPE: pOleVar = new COleVariant(cellData.getDoubleValue()); break;
default: return false;
}
range.put_Value2(*pOleVar);
delete pOleVar;
return true;
}
bool CPPTUtil::MergePPT(const std::string& outputPPTPath, const std::list<std::string>& lstMergePPTPath) {
CApplication pptApp;
COleException exception;
if (!pptApp.CreateDispatch("Powerpoint.Application", &exception)) return false;
pptApp.put_Visible(true);
CPresentations presentations = pptApp.get_Presentations();
CPresentation outPresention = presentations.Open(CString(outputPPTPath.c_str()), 0, 0, 1);
for (const auto& file : lstMergePPTPath) {
CPresentation mergePresention = presentations.Open(CString(file.c_str()), 0, 0, 1);
CSlides mergeSlides = mergePresention.get_Slides();
int pageNum = mergeSlides.get_Count();
mergePresention.Close();
CSlides outSlides = outPresention.get_Slides();
outSlides.InsertFromFile(CString(file.c_str()), outSlides.get_Count(), 1, pageNum);
}
outPresention.Save();
outPresention.Close();
pptApp.Quit();
return true;
}
本文完整覆蓋了 C++ 操作 PPT 的全流程:環境搭建、基礎對象封裝、文本修改、圖表數據更新(含 Excel 內嵌操作)、文件合並。關鍵難點在於圖表數據修改需激活內嵌 Excel 並正確釋放資源,合並功能則利用 InsertFromFile 實現頁面級拼接。