2023年12月11日发(作者:)
少年易学老难成,一寸光阴不可轻 - 百度文库
广丰鄂
摘要:
程序利用微软提供的excel操作的库函数读入数据,再调用MFC中的CDC类进行固定位置打印。
内容:
程序主要分两步:第一步从excel读取数据。第二步把excel读入的数据打印到纸张的固定位置。
从excel读取数据
一:准备工作
开始新建基于对话框的工程,记得在第四个向导中选择作为静态链接库导入。新建好之后导入excel操作库函数,依次选择View -> ClassWizard ->Add New Class
->From a type library。在弹出的对话框中选择装excel的安装目录,选择,然后添加类,主要类型有_Applicaiton, Workbooks, _Workbook, Worksheets,
_Wordsheet, Range类,其他类型可根据需要自己添加。
Excel接口类中层次如下所示:
-_Application
-Workbooks 工作薄集合
-_Workbook 工作薄
-Worksheets 工作表集合
-_Worksheet 工作表
-Range单元格区域
(在程序中可能还会使用到word类库,导入步骤一样,添加的类有_Application,
Documents, _Document, Selection, 因为word中的类可能与excel中的类名有冲突,可以在冲突的类中添加命名空间,在头文件和源文件中重复的类都包含到一个命名空间,这样就可以有效解决导入两个不同库而出现的类同名的问题)
导入excel库后,可以先看下导入的类提供的函数有哪些,一般可以根据其名字判断该函数的作用,如果不清楚你要做的步骤应该包含哪些函数,可以试下excel中提供的宏:
1.先打开excel应用程序,点击工具->宏->录制宏,开始录制。
2.进行你想要的操作,比如多打开工作博,或者添加工作簿,或者其他操作,操作结束后,点击结束宏。
3.查看录制的宏,点击工具->宏->宏。。。查看宏,本操作是一个已存在的文件,得到的宏如图1所示:
1 少年易学老难成,一寸光阴不可轻 - 百度文库
图1 打开存在文件的宏
4.分析宏,发现打开文件是在Wordbooks类的操作,使用的是Workbooks中的Open函数,然后可以查看导入的库中的Workbooks下的Open函数,选择正确的参数,即可执行打开文件操作。Workbooks下的Open函数原型如下:
PDISPATCH Workbooks::Open(LPCTSTR Filename, const VARIANT&
UpdateLinks, const VARIANT& ReadOnly, const VARIANT& Format, const
VARIANT& Password, const VARIANT& WriteResPassword, const VARIANT&
IgnoreReadOnlyRecommended, const VARIANT& Origin, const VARIANT&
Delimiter, const VARIANT& Editable, const VARIANT& Notify, const VARIANT&
Converter, const VARIANT& AddToMru, const VARIANT& Local, const
VARIANT& CorruptLoad);
会发现类中函数的参数几乎都是VARIANT类型的参数,Variant 是一种特殊的数据类型,除了定长String数据及用户定义类型外,可以包含任何种类的数据。Variant 也可以包含Empty、Error、Nothing及Null等特殊值。可以用VarType函数或TypeName函数来决定如何处理 Variant 中的数据。
可能会对这些类型不太了解,不过也没关系,碰到不明白的参数,不知道要填什么的时候,可以使用默认参数,默认参数可定义为如下:
COleVariant vTrue((short)TRUE);
COleVariant vFalse((short)FALSE);
COleVariant vOpt((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
准备工作就算完成了,接着就是正式使用编写代码操作excel了。
二:正式操作:
1.首先打开工程名 + Dlg结尾的对话框源文件,在头部添加#include “excel.h”和#include “atlbase.h”,要在文件中使用excel库函数,首先必须在此文件包含excel的头文件,atlbase是为了操作简单。
2.在功成名 + App结尾的源文件中的InitInstance中加入如下代码:
if (!AfxOleInit())
{
AfxMessageBox("初始化Ole失败!");
return FALSE;
}
3.在想要执行excel操作的程序函数或消息响应代码中添加对excel的代码。
A.首先定义类的对象:
spaceExcel::_Application excelApp;
Workbooks excelWorkBooks;
_Workbook excelWorkBook;
Worksheets excelWorkSheets;
_Worksheet excelWorkSheet;
2 少年易学老难成,一寸光阴不可轻 - 百度文库
Range excelRange, usedRange;
在_Application类中添加了一个命名空间并把此类包含在命名空间中。
B.打开excel应用程序:
if(excelApp == NULL){
if(!Dispatch(_T("ation")))
{
AfxMessageBox("系统检测到您的电脑尚未安装excel!,请先安装excel");
return;
}
}
如果想要看到此excel表格,可以在花括号后面添加:
ible(TRUE);
rControl(TRUE); //和word的区别。如果不加这句excel一闪就关
C.获得工作簿集合,工作簿,工作表集合,和工作表:
excelWorkBooks = kbooks();
excelWorkBook = (m_excelPathName, vOpt, vTrue, vOpt,
vOpt, vOpt, vOpt, vOpt, vOpt, vFalse, vOpt, vOpt, vOpt, vOpt, vOpt);
excelWorkSheets = ksheets();
excelWorkSheet = m(COleVariant((short)1));
具体参数和函数可参考类库。
D.获得已使用的行,列,得到行列的使用数目:
usedRange = dRange();
excelRange = s();
long iRowNum = nt();
excelRange = umns();
long iColumnNum = nt();
E.获得每个单元格的值:
VARIANT ret;
ret = ue(vOpt);
COleSafeArray sa(ret);
long lNumRows;
long lNumCols;
und(1, &lNumRows);
und(2, &lNumCols);
long index[2];
VARIANT val;
CString str = "";
int row, column;
3 少年易学老难成,一寸光阴不可轻 - 百度文库
for(row = m_startLocation; row <= iRowNum; row++){
for(column = 1; column <= iColumnNum; column++){
index[0] = row;
index[1] = column;
ment(index, &val);
switch(){
case VT_R8:
("%.2f", );
break;
case VT_BSTR:
str = (CString)l;
break;
case VT_EMPTY:
str = "";
break;
}
(str); //以CString保存单元格值
}
}
读取操作完成,如果要保存读取数据,可以使用CStringArray类型保存。
打印部分:
刚开始,不知道如何打印,网上百度,对于基于文档类型的工程实现打印很简单,但是基于对话框打印的就蛮复杂,看不怎么懂,网上代码也比较少。因此跑到学校图书馆去借书看,发现书上的简单也容易多了。通过CDC类自己编写打印功能。
一、准备工作
1.分辨率:分辨率是一个表示平面图像惊喜程序的概念,通常以横向和纵向点的数量来衡量的,表示水平点*垂直点的形式,在一个平面内,显示的点越多,分辨率就越高,显示的图像越细致,分辨率的种类有很多,主要了解下屏幕分辨率和设备分辨率。
屏幕分辨率:觉得出现在屏幕上的信息数量(以像素为单位)的设置,低分辨率能使屏幕上项目大一些,但屏幕区域会变小,高分辨率扩大了整个屏幕区域,但单个项目会变小。
设备分辨率:又称输出分辨率,指的是各类输出设备每英寸可产生的点数,如显示器,喷墨打印机,激光打印机,绘图仪的分辨率。这种分辨率通过DPI衡量,PC显示器的设备分辨率一般在60~120DPI之间,而打印设备的分辨率在360~1440DPI之间。
2.映射模式:
因为分辨率的不同,因此需要一种映射模式来解决这个问题,使打印效果和屏幕上显示的相同。映射模式反映了逻辑设备单位与实际物理坐标单位之间的对应转4 少年易学老难成,一寸光阴不可轻 - 百度文库
换关系,映射模式可通过设备环境类的一个成员函数SetMapMode来设置。
Virtual int SerMapMode(int nMapMode);具体参数可参见MSDN。
二、正式操作:
添加一个按键,响应打印操作。在响应函数内部进行如下操作:
1.获取设备上下文。
A. 如果已经知道打印机的设备名称,可通过CDC类中的CreateDC方法创建打印机的设备上下文。
CDC tempdc;
DC(“”, “HP LaserJet 1020”, “”, “”);
具体参数可参见msdn。
B. 如果想要使用打印机设备而不知道设备名称,可以调用打印对话框使用户选择打印机,然后调用CPrintDialog类的GetPrinterDC方法获得设备上下文。
DWORD dwflags = PD_PAGENUMS | PD_HIDEPRINTTOFILE |PD_SELECTION;
CPrintDialog dlg(false, dwflags, NULL);
If(l() == IDOK)
{
CDC dc;
h(nterDC());
}
C. 如果不想选择打印机,也可以使应用程序调用当前机器默认的打印机,可以通过CPritDialog类的GetPrinterDC方法来实现,或者在构造打印机对话框时设置其具有PD_RETURNDEFAULT风格。
DWORD dwflags = PD_PAGENUMS | PD_HIDEPRINTTOFILE |
PD_RETURNDEFAULT;
CPrintDialog dlg(false, dwflags, NULL);
aults();
nterDC();
2.获得了设备上下文,接下来打印文本信息就很简单了。直接调用设备上下文类中提供的TextOut函数直接打印输出字符就可以了。不过为了准确定位,还得有一个好的映射:
A.首先定义个CDC* pDC = GetDC();用于获得对话框的的大小。然后用打印设备上下文CDC dc;获得他们之间的映射关系:
double ratex = iceCaps(LOGPIXELSX) /
pDC->GetDeviceCaps(LOGPIXELSX);
double ratey = iceCaps(LOGPIXELSY) /
pDC->GetDeviceCaps(LOGPIXELSY);
这个程序采用的是打印编辑框,把所有的编辑框ID设置为1,2,3。。。便于操作,定义两个CRect对象:一个是打印区域的大小,一个是编辑框的大小,获得他们的大小,并根据编辑框的位置在固定位置上打印编辑框的文本信息,具体代码如下:
CRect rect, framerect;
5 少年易学老难成,一寸光阴不可轻 - 百度文库
m_dowRect(&framerect);
char classname[255];
for(int i = 1; i <= 18; i++)
{
CWnd* control = this->GetDlgItem(i);
if(NULL != control)
{
CString str;
// CFont font;
control->GetWindowText(str);
control->GetWindowRect(&rect);
GetClassName(control->GetSafeHwnd(), classname, 255);
if(strcmp(classname, "Edit") == 0)
{
// PointFont(200 * ratex, "宋体");
t(( - ) * ratex, ( -
) * ratey, str);
}
}
}
m_Object();
();
3.可以使用DEVMODE结构控制打印。DEVMODE结构可以在msdn中查看。如改变文字方向:
DWORD dwflags = PD_ALLPAGES | PD_NOPAGENUMS |
PD_USEDEVMODECOPIES | PD_SELECTION | PD_HIDEPRINTTOFILE |
PD_RETURNDEFAULT
CPrintDialog dlg(false, dwflags, NULL);
If(l() == IDOK)
{
LPDEVMODE dv = Mode();
If(isHengXiang)
{
dv->dmOrientation = DMORIENT_LANDSCAPE;
}else{
dv->dmOrientation = DMORIENT_PORTRAIT;
}
CDC dc;
(nterDC());
(dv);
6 少年易学老难成,一寸光阴不可轻 - 百度文库
}
总结:
有这两个操作再加上MFC的一些基本操作和控件处理,就可以完成从excel中读出数据并以特定格式打印到打印纸上。
其实,如果要把excel数据用特定格式打印到纸面上,可以不用这么复杂,可以直接用excel直接完成上面的两个步骤。不过excel不怎么熟悉。没有具体步骤。
参考:
从excel读数据主要参考百度出来的各种网页上的代码,很详细,也很简单。
打印操作参考书:
Visual C++ 开发实战宝典, 宋珅等编著, 清华大学出版社2010年1月第1版。
ISBN:978 7 302 20905 8
7


发布评论