婴儿 发表于 2010-5-18 17:52:25

参数化Excel单元格

首先声明,这不是一种适用于所有情况的普遍办法,只适用于定长的Excel和单元格,并且要参数化的单元格不多,参数化的值中也不能包含中文。
问题的缘起是一个Excel的导入功能:在导入Excel后,会刷出一个记录列表的页面,在这里选择刚才导入的那条记录,进行后续处理。为了在记录列表页面让所有Vuser选到自己的记录,需要使用这里的查询功能,而查询条件里能做为唯一标志的两个字段,一个是自动生成的,另一个在Excel里填写,它们都不能在这之前通过关联获得,它们都是在记录列表这个页面返回的。姑不论这样的程序设计是否合理,这里仅就Excel单元格的参数化问题进行探讨。
为了得到唯一的查询条件,只能通过参数化Excel表中的那个单元格来实现(姑且把它叫做 编号),除非你愿意手工生成N多Excel,并且这些Excel中的编号都不同。
我经常用的方法是使用时间参数来做唯一标志,这里也用这个参数来填充 编号 这个单元格,为了唯一标志每个Vuser使用的Excel文件,也用这个参数命名Excel文件。
以前常用的格式为 %Y-%m-%d %H:%M:%S.000,因为冒号不能作为文件名,所以这次改为 %Y-%m-%d %H.%M.%S.000,即如 2010-05-18 13.33.42.456。
用UltraEdit打开这个Excel文件,找到相应位置,如下图:

我们要参数化的就是这个时间,2010的2对应的位置是174aH,脚本实现如下,说明请看注释:

char wfilename;//定义全局变量,以便在导入Excel文件后删除该文件
Action()
{

//生成Excel文件,使Excel中 编号 带时间信息
{
char * rfilename = "D:\\批量导入2010-05-18 13.33.42.456.xls";
long file_stream,file;
char * buffer,* p;
int count,i;
char * time=lr_eval_string("{时间}"); //将{时间}参数格式设为 %Y-%m-%d %H.%M.%S.000

buffer = (char *)malloc(512000*1);

//下三句生成新Excel文件名
strcpy(wfilename,"D:\\批量导入");
strcat(wfilename,time);
strcat(wfilename,".xls");

if ((file_stream = fopen(rfilename, "rb")) == NULL ) {//只能以二进制方式打开Excel文件,.csv和.txt等文本文件都不支持多工作表的Excel文件
lr_error_message ("Cannot open %s", rfilename);
return -1;
}

count = fread(buffer, 1, 512000, file_stream);

p=buffer+0x174a; //到Excel单元格中时间字符串开始的位置,以做下面的替换
for (i=0;i<strlen(time);i++) {
   *(p+i)=*(time+i);
}
//不能使用字符串函数如strcpy()、strcat()等进行处理,因为Excel文件中一开始就有很多字符串的结束标志符\0

if ((file = fopen(wfilename, "wb")) == NULL) {
lr_output_message ("Unable to create %s", wfilename);
return -1;
}

fwrite(buffer, 1, count, file);

fclose(file);
}

/*导入Excel*/
……

web_submit_data("导入Excel",
"Action=http://……",
"Method=POST",
"EncType=multipart/form-data",
"RecContentType=text/html",
"Referer=http://……",
"Snapshot=t261.inf",
"Mode=HTTP",
ITEMDATA,
……
"Name=file", "Value=D:\\\\批量导入{时间}.xls", "File=Yes", ENDITEM,
LAST);

……

//导入完成后,删除上面新生成的Excel文件
remove(wfilename);

/*查询*/

//从查询结果中取关联数据,为后续处理用
web_reg_save_param(……);

web_submit_data("条件查询",
"Action=http://……",
"Method=POST",
"Referer=http://……",
"Snapshot=t284.inf",
"Mode=HTTP",
ITEMDATA,
……
"Name=number", "Value={时间}", ENDITEM,
……
LAST);

/*后续处理*/

return 0;
}

也许有人会问,为什么不在脚本中搜索时间串对应的位置,而要用UltraEdit来找呢,因为Excel二进制流无法使用字符串函数来搜索(有很多\0),只能逐字符搜索,效率很低。

如果单元格中有中文,情况有些不一样。例如我们将编号值填为 编号2010-05-18 13.33.42.456,用UltraEdit打开该文件,可能找不到时间串,但是反复修改后又可能找得到(这是不确定的!汗,我也不知道为什么。简单地,多加1个英文字符一般能够找到)。找到的情况不太一样,如下图:

时间串的每个字符间多了个不可见字符00H,在脚本中只需修改2处:
p=buffer+0x174a; 改为 p=buffer+0x180c;
*(p+i)=*(time+i); 改为 *(p+i*2)=*(time+i);

以上方法适用范围很窄,相当于将原文件作为一个模板,复制出一堆大同小异的Excel文件。无法用中文作为参数值,也无法处理变长的Excel和单元格。请同好高人指教。(Dll的方法应该具有更强的处理能力和普适性,但也没有现成的东东,要自己去写。或者还有其他的什么办法?)

附上脚本和Excel原文件:

PrefTest 发表于 2010-5-18 21:20:14

C语言操作Excel好像有个CSpreadSheet.h头文件可以用

tiduscy83 发表于 2013-11-13 22:02:30

回复 1# 婴儿


    学习下

tiduscy83 发表于 2013-11-13 22:02:33

回复 1# 婴儿


    学习下

tiduscy83 发表于 2013-11-13 22:03:57

学习下
页: [1]
查看完整版本: 参数化Excel单元格