VS中导出PDF
程序员文章站
2022-07-13 13:31:12
...
需要准备的头文件:
///- 2. 初始化PDF
HPDF_Doc CPageOutput::initPdf(char * filename)
{
HPDF_Doc pdf;
pdf = HPDF_New(error_handler,NULL); ///-创建一个pdf句柄
if (NULL == pdf) { return NULL; } ///- 创建句柄错误
int retEnv = setjmp(g_env);
if (0!=retEnv) ///-查看是否句柄产生异常
{
CString warningMsg = CString("创建/替换 PDF文件异常, 以\"")+CString(filename) +
CString("\"命名的文件可能已经打开,请检查并关闭文件后 重试!");
MessageBox(warningMsg, TEXT("提示"));
/// HPDF_Free(pdf);
return NULL;
}
//// 设定压缩模式
HPDF_STATUS retStat = HPDF_SetCompressionMode(pdf,HPDF_COMP_ALL);
if (HPDF_OK == retStat)
{
retStat = HPDF_SetPageMode(pdf,HPDF_PAGE_MODE_USE_OUTLINE);
if (HPDF_OK != retStat) { return NULL; }
}
else
{ return NULL; }
//// 设置CN Simple 中文简体 字符
retStat = HPDF_UseCNSFonts(pdf);
if (HPDF_OK != retStat) { return NULL; }
//// 设置CN Simple 中文简体 编解码
retStat = HPDF_UseCNSEncodings(pdf);
if (HPDF_OK != retStat) { return NULL; }
return pdf;
}
//-- a. 添加页面
bool CPageOutput::pdfAddPage()
{
o_page = HPDF_AddPage(o_pdf); ///- 在文档中新增一页
o_font = HPDF_GetFont(o_pdf, "SimSun", "GB-EUC-H"); ///- 生成字体
///- 设置页面大小为A4,后面一个参数是描述
HPDF_STATUS retStat = HPDF_Page_SetSize(o_page,HPDF_PAGE_SIZE_A4,HPDF_PAGE_PORTRAIT);
if (HPDF_OK != retStat) { return false; }
return true;
}
//-- b. PDF画线
bool CPageOutput::drawHLine (HPDF_Page page,Point2f startPt, Point2f endPt)
{
HPDF_STATUS retStat = HPDF_Page_BeginText(page);
if (HPDF_OK != retStat) { return false; }
retStat = HPDF_Page_MoveTextPos(page, startPt.x, startPt.y);
if (HPDF_OK != retStat) { return false; }
retStat = HPDF_Page_EndText(page);
if (HPDF_OK != retStat) { return false; }
retStat = HPDF_Page_MoveTo(page, startPt.x, startPt.y);
if (HPDF_OK != retStat) { return false; }
retStat = HPDF_Page_LineTo(page, endPt.x, endPt.y);
if (HPDF_OK != retStat) { return false; }
retStat = HPDF_Page_Stroke(page);
if (HPDF_OK != retStat) { return false; }
return true;
}
//-- c. PDF文本输出
bool CPageOutput::pdfTextOut(HPDF_Page Page,HPDF_Font font, HPDF_REAL fontSz, Point2f pt,const char* szText)
{
HPDF_STATUS retStat;
retStat = HPDF_Page_BeginText(Page); ///- 设置页面
if (HPDF_OK != retStat) { return false; }
retStat = HPDF_Page_SetFontAndSize(Page, font, fontSz); ///- 设置字体和字号
if (HPDF_OK != retStat) { return false; }
retStat =HPDF_Page_MoveTextPos(Page, pt.x,pt.y); ///- 设置开始位置
if (HPDF_OK != retStat) { return false; }
retStat = HPDF_Page_ShowText(Page, szText); ///- 设定要显示的字符串
if (HPDF_OK != retStat) { return false; }
retStat = HPDF_Page_EndText(Page); ///- 页面结尾
if (HPDF_OK != retStat) { return false; }
return true;
}
///- 3. 打印页面框架 调用b, c, 打印包括文件标题 表头 页脚等内容---------(3.7改)
bool CPageOutput::pdfPrintPgFrame(int nowID, int pgTotal)
{
char spec[128] ="规格; ";
char batch[128] ="批次: ";
strcat_s(spec,128,CStringA(o_spec).GetBuffer());
strcat_s(batch,128,CStringA(o_batch).GetBuffer());
const char * page_title = "XXXXXXX检测结果", ///文件页眉
* page_1st_spec =spec,
* page_1st_batch = batch,
* page_1st_oper = "操作员:______________",
* page_1st_timeTag = "日期:______________",
* table_col_id = "序号", ///- 字号(pond):10.5 表头信息-序号
* table_col_result = "检测结果"; ///- 字号(pond):10.5 表头信息-结果值
////=PDF生成的 过程 Y坐标是从左下角开始的
float tablePosY = 0.0;
bool boolRet=false;
if (2 > nowID) ///- 如果是首页,则打印文件头
{ ///- 显示首页页眉
boolRet = pdfTextOut(o_page, o_font, 12.0f, Point2f(8.0f*o_scaleX, o_pgHeight-3.0f*o_scaleY), page_title);
if (!boolRet) { return false; }
//// 操作员:______________ (5.5, 4.0)日期:______________ (12.5, 4.0)
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(5.5f*o_scaleX, o_pgHeight-4.0f*o_scaleY), page_1st_spec);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(12.5f*o_scaleX, o_pgHeight-4.0f*o_scaleY), page_1st_batch);
if (!boolRet) { return false; }
//// 显示首页 标记信息 操作员:______________ (5.5, 5.0) 日期:______________ (12.5, 5.0)
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(5.5f*o_scaleX, o_pgHeight-5.0f*o_scaleY), page_1st_oper);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(12.5f*o_scaleX, o_pgHeight-5.0f*o_scaleY), page_1st_timeTag);
if (!boolRet) { return false; }
//// 定义表头Y坐标 序号 (4.5, 4.8) 检测结果(10.5, 4.8); 横线坐标 (3, 5.0)(18, 5.0)
tablePosY = o_pgHeight-5.8f*o_scaleY;
///-画纵向线分割每组------------------------(3.7改)
//横坐标为每组间隔中点: 6; 10.5; 15
boolRet = drawHLine(o_page, Point2f(6.0f*o_scaleX,o_pgHeight-6.0f*o_scaleY), Point2f(6.0f*o_scaleX, 1.3f*o_scaleY));
if (!boolRet) { return false; }
boolRet = drawHLine(o_page, Point2f(10.5f*o_scaleX,o_pgHeight-6.0f*o_scaleY), Point2f(10.5f*o_scaleX, 1.3f*o_scaleY));
if (!boolRet) { return false; }
boolRet = drawHLine(o_page, Point2f(15.0f*o_scaleX,o_pgHeight-6.0f*o_scaleY), Point2f(15.0f*o_scaleX, 1.3f*o_scaleY));
if (!boolRet) { return false; }
}
else
{ ///- 定义表头Y坐标序号 (4.5, 1.8) 检测结果(10.5, 1.8); 横线坐标 (3, 2.0)(18, 2.0)
tablePosY = o_pgHeight-1.8f*o_scaleY;
///-画纵向线分割每组------------------------(3.7改)
//横坐标为每组间隔中点: 5.75; 10.25; 14.75;
boolRet = drawHLine(o_page, Point2f(6.0f*o_scaleX,o_pgHeight-2.0f*o_scaleY), Point2f(6.0f*o_scaleX, 1.3f*o_scaleY));
if (!boolRet) { return false; }
boolRet = drawHLine(o_page, Point2f(10.5f*o_scaleX,o_pgHeight-2.0f*o_scaleY), Point2f(10.5f*o_scaleX, 1.3f*o_scaleY));
if (!boolRet) { return false; }
boolRet = drawHLine(o_page, Point2f(15.0f*o_scaleX,o_pgHeight-2.0f*o_scaleY), Point2f(15.0f*o_scaleX, 1.3f*o_scaleY));
if (!boolRet) { return false; }
}
//// 显示表头--------(3.7改)
/*
每个PDF打印4列;把一列序号和一列结果分为一组,共四组;
组内,列于列间隔2个单位;组与组之间间隔2.5个单位;每页总宽21个单位,总长30个单位;
表头排列横坐标如下;
2-3.5 | 6.5-8 | 11-12.5 | 15.5_17
*/
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(2.0f*o_scaleX, tablePosY), table_col_id);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(6.5f*o_scaleX, tablePosY), table_col_id);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(11.0f*o_scaleX, tablePosY), table_col_id);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(15.5f*o_scaleX, tablePosY), table_col_id);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(3.5f*o_scaleX, tablePosY), table_col_result);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(8.0f*o_scaleX, tablePosY), table_col_result);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(12.5f*o_scaleX, tablePosY), table_col_result);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(17.0f*o_scaleX, tablePosY), table_col_result);
if (!boolRet) { return false; }
//// 页脚分割线 横线坐标 首页: start (3, 5.0) end (18, 5.0) 其它: start (3, 2.0) end (18, 2.0)
boolRet = drawHLine(o_page, Point2f(1.5f*o_scaleX, tablePosY-0.2f*o_scaleY), Point2f(19.5f*o_scaleX, tablePosY-0.2f*o_scaleY));
if (!boolRet) { return false; }
//// 显示页脚
char indexBuf[20]="";
sprintf_s(indexBuf, "%d/%d", nowID, pgTotal);
//// 画水平线分割 并打印 ”第 12/25 页“
boolRet = drawHLine(o_page, Point2f(1.5f*o_scaleX,1.3f*o_scaleY), Point2f(19.5f*o_scaleX, 1.3f*o_scaleY));
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(9.0f*o_scaleX, 0.8f*o_scaleY), "第");
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(9.8f*o_scaleX, 0.8f*o_scaleY), indexBuf);
if (!boolRet) { return false; }
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(11.0f*o_scaleX, 0.8f*o_scaleY), "页");
if (!boolRet) { return false; }
///-画纵向线分割每组------------------------(3.7改)
boolRet = drawHLine(o_page, Point2f(3.0f*o_scaleX,1.3f*o_scaleY), Point2f(18.0f*o_scaleX, 1.3f*o_scaleY));
return true;
}
//-- d. 内容整页打印 调用c 循环打印内容,一次打印一整页;
bool CPageOutput::pdfPrintTxt(int lineTotal, int pgID, vector<CString> resBank)
{
char lineBuf[10]="", resultBuf[20]="";
bool boolRet=false;
float beginPos=0.0;
int gapID=0, ///- 序号偏差,即当不在首页的时候,将偏差值加到序号上面
realLineID=0; ///- realLineID 当前序号和gapID组合后的序号真实值
//首页每组最多存储45条数据;首页最多存储45*4 = 180 条数据;
//其他页最多存储53*4 = 212条数据;
if ( 2 > pgID)
{ ///- 首页的 首行 Y坐标
beginPos = o_pgHeight-6.0f*o_scaleY;
for (int lineID=1; lineID<=lineTotal; lineID++)
{ ///- 开始写结果数据
realLineID = lineID+gapID;
ZeroMemory(lineBuf,10);
ZeroMemory(resultBuf, 20);
sprintf_s(lineBuf, "%d", realLineID);
sprintf_s(resultBuf, "%S", resBank[realLineID-1]);
switch((lineID - 1) / 45)
{
case 0:
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(2.0f*o_scaleX, beginPos-0.5f*lineID*o_scaleY), lineBuf);
if (!boolRet) { return false; }
boolRet=pdfTextOut(o_page, o_font, 10.5f, Point2f(3.5f*o_scaleX, beginPos-0.5f*lineID*o_scaleY), resultBuf);
if (!boolRet) { return false; }
break;
case 1:
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(6.5f*o_scaleX, beginPos-0.5f*(lineID - 45)*o_scaleY), lineBuf);
if (!boolRet) { return false; }
boolRet=pdfTextOut(o_page, o_font, 10.5f, Point2f(8.0f*o_scaleX, beginPos-0.5f*(lineID - 45)*o_scaleY), resultBuf);
if (!boolRet) { return false; }
break;
case 2:
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(11.0f*o_scaleX, beginPos-0.5f*(lineID - 90)*o_scaleY), lineBuf);
if (!boolRet) { return false; }
boolRet=pdfTextOut(o_page, o_font, 10.5f, Point2f(12.5f*o_scaleX, beginPos-0.5f*(lineID - 90)*o_scaleY), resultBuf);
if (!boolRet) { return false; }
break;
case 3:
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(15.5f*o_scaleX, beginPos-0.5f*(lineID - 135)*o_scaleY), lineBuf);
if (!boolRet) { return false; }
boolRet=pdfTextOut(o_page, o_font, 10.5f, Point2f(17.0f*o_scaleX, beginPos-0.5f*(lineID - 135)*o_scaleY), resultBuf);
if (!boolRet) { return false; }
break;
}
}
}
else
{ ///- 其他页面的首行 Y坐标
beginPos = o_pgHeight-2.0f*o_scaleY;
gapID = 45*4 + (pgID-2)*53*4;
for (int lineID=1; lineID<lineTotal; lineID++)
{ ///- 开始写结果数据
realLineID = lineID+gapID;
ZeroMemory(lineBuf,10);
ZeroMemory(resultBuf, 20);
sprintf_s(lineBuf, "%d", realLineID);
sprintf_s(resultBuf, "%S", resBank[realLineID-1]);
switch((lineID - 1) / 53)
{
case 0:
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(2.0f*o_scaleX, beginPos-0.5f*lineID*o_scaleY), lineBuf);
if (!boolRet) { return false; }
boolRet=pdfTextOut(o_page, o_font, 10.5f, Point2f(3.5f*o_scaleX, beginPos-0.5f*lineID*o_scaleY), resultBuf);
if (!boolRet) { return false; }
break;
case 1:
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(6.5f*o_scaleX, beginPos-0.5f*(lineID - 53)*o_scaleY), lineBuf);
if (!boolRet) { return false; }
boolRet=pdfTextOut(o_page, o_font, 10.5f, Point2f(8.0f*o_scaleX, beginPos-0.5f*(lineID - 53)*o_scaleY), resultBuf);
if (!boolRet) { return false; }
break;
case 2:
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(11.0f*o_scaleX, beginPos-0.5f*(lineID - 106)*o_scaleY), lineBuf);
if (!boolRet) { return false; }
boolRet=pdfTextOut(o_page, o_font, 10.5f, Point2f(12.5f*o_scaleX, beginPos-0.5f*(lineID - 106)*o_scaleY), resultBuf);
if (!boolRet) { return false; }
break;
case 3:
boolRet = pdfTextOut(o_page, o_font, 10.5f, Point2f(15.5f*o_scaleX, beginPos-0.5f*(lineID - 159)*o_scaleY), lineBuf);
if (!boolRet) { return false; }
boolRet=pdfTextOut(o_page, o_font, 10.5f, Point2f(17.0f*o_scaleX, beginPos-0.5f*(lineID - 159)*o_scaleY), resultBuf);
if (!boolRet) { return false; }
break;
}
}
}
return true;
}
///- 4. 打印到PDF文档中 调用a 添加页面, 调用3打印页面框架, 调用d打印全部的检测结果-------------(3.7改);
bool CPageOutput::print2PDF(int recordCnt, vector<CString> resBank)
{
o_scaleX = o_pgWidth/PAGE_WIDTH, o_scaleY = o_pgHeight/PAGE_HEIGHT;
//// 首页 最多47条记录,第一行坐标 1 (4.5, 5.5) 129.8973 (11.5, 5.5)
/// 其他 最多53条记录,第一行坐标 48 (4.5, 2.5) 192.9378 (11.5, 2.5) 48 = 首页47+第二页的1
int nowID=0, pgTotal=0, lastCnt=0;
if (recordCnt<181) { pgTotal=1; }
else
{
recordCnt -= 45*4;
pgTotal =1 + recordCnt/212;
lastCnt = recordCnt%212;
///- 如果不是完整页面 则添加一个页面
if (0 < lastCnt) { pgTotal = pgTotal +1; }
}
bool boolRet=false;
//// 打印首页框架
boolRet = pdfPrintPgFrame(1, pgTotal);
if (!boolRet) { return false; }
char lineBuf[10]="";
if (pgTotal<2) ///- 结果条目少于1页的情况
{
boolRet = pdfPrintTxt(recordCnt, 1, resBank);
if (!boolRet) { return false; }
}
else ///- 条目多于1页的情况
{
int pgID=1;
boolRet = pdfPrintTxt(180, pgID, resBank); ///- 打印首页
if (!boolRet) { return false; }
//// 打印中间页
for (pgID=2; pgID<(pgTotal); pgID++)
{
if (pdfAddPage())
{
boolRet = pdfPrintPgFrame(pgID, pgTotal);
if (!boolRet) { return false; }
boolRet = pdfPrintTxt(212, pgID, resBank);
if (!boolRet) { return false; }
}
else { return false; }
}
//// 打印尾页
if (pdfAddPage())
{
boolRet = pdfPrintPgFrame(pgID, pgTotal);
if (!boolRet) { return false; }
boolRet = pdfPrintTxt(lastCnt, pgTotal, resBank);
if (!boolRet) { return false; }
}
else { return false; }
}
return true;
}