在学习工作中经常会使用到WPS或者其他的表格文档处理,尤其是在表格中经常会用到一些公式或者计算处理数据,比较简单的取最大或者最小那些都还好,但是如果涉及到的数据太多或者需要循环处理的时候就比较麻烦了。
例如我想通过表格获取一个累加的数值,1,2,3,5,8,13.......这种数据之间相互影响的数据或者是需要循环判断的计算时就会存在不知如何使用公式的尴尬情况。但是如果你能自定义功能就不必担心这些问题了,后续以常用的收集卡牌为实例。
要求规则:卡牌分为A/B/C/D/E五类卡牌,其中每类都有一张就可以兑换S卡牌,其他三类卡牌各一张就可以兑换X卡牌。已知A/B/C/D/E五类卡牌的数量,自动计算出S、X卡牌数量。
例如:
A卡数 | B卡数 | C卡数 | D卡数 | E卡数 |
5 | 3 | 2 | 1 | 3 |
兑换S卡的数量比较容易获得,只要把所有卡数量从小到大排序取最小就得到了
排序后的数量为 1(E卡) 2(C卡) 3(B卡) 3(E卡) 5(A卡)
所以S卡能兑换1张 ,兑换后剩余情况为 0(E卡) 1(C卡) 2(B卡) 2(E卡) 4(A卡)
剩余的X卡数量就比较复杂了,需要不断的排序和兑换,并且需要判断是否还能兑换卡片
0(E卡) 1(C卡) 2(B卡) 2(E卡) 4(A卡) <<兑换S卡后剩余卡牌数
0(E卡) 1(C卡) 1(B卡) 1(E卡) 3(A卡) <<兑换X卡后数量 1张
0(E卡) 1(C卡) 0(B卡) 0(E卡) 2(A卡) <<兑换X卡后数量 2张
0(E卡) 1(C卡) 0(B卡) 0(E卡) 2(A卡) <<兑换X卡后剩余卡牌数
以上能兑换的卡牌数为 1张S卡,2张X卡。
但是以上过程只是一个简单的演算,而且是需要取判断和处理的结果,可能要得到S卡使用公式还是可以得到的,但是后面的X卡用xlsx表格里面的公式实现起来就比较复杂了,接下来本文将会介绍一种比较适合简单运算处理且需要循环判断的处理表格数据的办法。
这个文档也可以在原有文件上进行添加,但是如果是第一次尝试防止数据丢失还是先进行测试为好,以免数据被误删或者修改。
将表格另存为一个Microsoft Excel 启用宏的工作簿 、后缀为(.xlsm),其特别之处在于启用了宏定义,这个步骤不能省去,否则无法启用宏定义。
完成以上操作后,即可得到一个启用宏定义的表格文件。
打开文档后,点击开发工具 >>切换到JS环境>>WPS宏编辑器。
点击后会自动打开宏编辑器,并且为你创建一个Module1的空白宏定义模板,如下图所示.......
>>这里的作用是为了防止在对行、列进行操作时存在错误,以及数据读写的时候能够更准确地进行做的一个准备工作,可根据不同的小功能进行备注修改,每个人可以根据不同情况进行设计。
宏定义被触发是有条件的,这里以行数据(第3行)改变为触发条件,可以选择SheetChange(Sh, rg)函数。
选择后,编辑器会根据你的触发条件创建一个功能函数,只要在这个函数内完成写下处理过程就可以完成自定义的功能了。
因为SheetChange的触发机制是全表格内的改变都会进行,所以需要进行调整为第三列才进行操作,修改如下:
function Application_SheetChange(Sh, rg)
{
let hang=rg.Row; //记录行
let lie=rg.Column;//记录列
if(hang==3)
{
// 处理功能
}
}
这样一来,数据只有在第三行发生变化时才会进行处理,可以根据需要改成其他行或者列。
确定了修改的行位置,现在需要读取第三行指定位置的数据方便进行处理,这时就需要一些输入和输出功能了,
function Application_SheetChange(Sh, rg)
{
let hang=rg.Row; //记录行
let lie=rg.Column;//记录列
if(hang==3)
{
//常规读写
let A_NUM= Range("C3").Value2; //将C3位置的值读取到 A_NUM
Application.Range("C4").Value2=0;//将C4位置的值改成 0
//带参数读
let B_NUM=Application.Worksheets.Item(1).Cells.Item(3,4).Value2;
//将D3位置的值读取到 B_NUM
//带参数写1
Application.Worksheets.Item("Sheet1").Activate() //打开Sheet1表格
let rng = Range("A1:G5"); //涉及修改的表格区域
rng.Cells.Item(5,4).Value2 = 1; // Item(行,列) 将D5的值改为1
//带参读写2
Application.Worksheets.Item(1).Cells.Item(hang,lie).Value2=1; //带参写
num=Application.Worksheets.Item(1).Cells.Item(hang,30).Value2; //带参读
}
}
function Application_SheetChange(Sh, rg)
{
let hang=rg.Row; //记录行
let lie=rg.Column;//记录列
if(hang==3)
{
var card=[0,0,0,0,0];//定义初始数组
//对多个数据进行读取
card[0]=Application.Worksheets.Item(1).Cells.Item(3,3).Value2;//读取A类卡
card[1]=Application.Worksheets.Item(1).Cells.Item(3,4).Value2;//读取B类卡
card[2]=Application.Worksheets.Item(1).Cells.Item(3,5).Value2;//读取C类卡
card[3]=Application.Worksheets.Item(1).Cells.Item(3,6).Value2;//读取D类卡
card[4]=Application.Worksheets.Item(1).Cells.Item(3,7).Value2;//读取E类卡
//带参数写
Application.Worksheets.Item("Sheet1").Activate() //打开Sheet1表格
let rng = Range("A1:G8"); //涉及修改的表格区域
rng.Cells.Item(6,3).Value2 = card[0]; // 将读到的A卡数打印在C6
rng.Cells.Item(6,4).Value2 = card[1]; // 将读到的B卡数打印在D6
rng.Cells.Item(6,5).Value2 = card[2]; // 将读到的C卡数打印在E6
rng.Cells.Item(6,6).Value2 = card[3]; // 将读到的D卡数打印在F6
rng.Cells.Item(6,7).Value2 = card[4]; // 将读到的E卡数打印在G6
}
}
根据处理的数据量完成对多个表格内的数据进行读取和多个位置的数据进行修改。修改为上述代码后,点击运行宏就可以看到表格内也发生了变化。
上面的功能就是把第三行的数据从C3-G3整个复制并显示到第6行,修改第三行的数据时,第6行会自动更新为修改后的值。
前面的操作只是为了熟悉这个操作逻辑和新手学习操作,后跟代码为整个计算处理功能。
实现代码如下:
function Application_SheetChange(Sh, rg)
{
let hang=rg.Row; //记录行
let lie=rg.Column;//记录列
if(hang==3)
{
var card=[0,0,0,0,0];//定义初始数组
var orde=[0,1,2,3,4];//记录卡组顺序
//对多个数据进行读取
card[0]=Application.Worksheets.Item(1).Cells.Item(3,3).Value2;//读取A类卡
card[1]=Application.Worksheets.Item(1).Cells.Item(3,4).Value2;//读取B类卡
card[2]=Application.Worksheets.Item(1).Cells.Item(3,5).Value2;//读取C类卡
card[3]=Application.Worksheets.Item(1).Cells.Item(3,6).Value2;//读取D类卡
card[4]=Application.Worksheets.Item(1).Cells.Item(3,7).Value2;//读取E类卡
for(let i=0;i<5;i++) /****从小到大排序*****/
for(let j=0;j<5;j++)
{
if(card[j]>card[j+1])
{
var temp=card[j+1]; card[j+1]=card[j]; card[j]=temp;
temp=orde[j+1]; orde[j+1]=orde[j]; orde[j]=temp;
}
}
let s; s=0; //初始化S卡值
if(card[0]!=0) //最小值不为0
{
s=card[0]; //记录S卡的兑换数量
card[0]=card[0]-s;
card[1]=card[1]-s;
card[2]=card[2]-s;
card[3]=card[3]-s;
card[4]=card[4]-s; //扣除兑换s卡所需的卡
}
for(let i=0;i<5;i++) /****从小到大排序*****/
for(let j=0;j<5;j++)
{
if(card[j]>card[j+1])
{
var temp=card[j+1]; card[j+1]=card[j]; card[j]=temp;
temp=orde[j+1]; orde[j+1]=orde[j]; orde[j]=temp;
}
}
let x; x=0; //初始化x卡值
while(card[2]>0)
{
card[2]--;
card[3]--;
card[4]--; //扣除兑换X卡所需的卡
x++; //X数量+1
for(let i=0;i<5;i++) /****从小到大排序*****/
for(let j=0;j<5;j++)
{
if(card[j]>card[j+1])
{
var temp=card[j+1]; card[j+1]=card[j]; card[j]=temp;
temp=orde[j+1]; orde[j+1]=orde[j]; orde[j]=temp;
}
}
}
//带参数写
Application.Worksheets.Item("Sheet1").Activate() //打开Sheet1表格
let rng = Range("A1:G8"); //涉及修改的表格区域
rng.Cells.Item(5,4).Value2 = s; // S卡数打印在D5
rng.Cells.Item(5,6).Value2 = x; // X卡数打印在F5
rng.Cells.Item(4,3).Value2 = card[orde[0]]; // 将读到的A卡数打印在C4
rng.Cells.Item(4,4).Value2 = card[orde[1]]; // 将读到的B卡数打印在D4
rng.Cells.Item(4,5).Value2 = card[orde[2]]; // 将读到的C卡数打印在E4
rng.Cells.Item(4,6).Value2 = card[orde[3]]; // 将读到的D卡数打印在F4
rng.Cells.Item(4,7).Value2 = card[orde[4]]; // 将读到的E卡数打印在G4
}
}
6.功能实现
完成宏定义功能的撰写后,就可以发现表格已经自动完成了计算处理工作。
修改不同的拥有卡,表格就会自动得出剩余卡以及能兑换卡数量。
后记:以上仅是为了解决一些手头的数据处理而撰写的小功能,可能存在一些歧义或者错误,欢迎读者和大佬指点纠错,有疑惑的小伙伴也可评论留言,我会进行解答和分享补充。
时间:2021/12/26
平台:WPS Office Win10专业版(64位)
相关参考链接:WPS JSA 宏编程(JS):1.初识 - nutix - 博客园
WPS JS宏的示例——项目阶段检测 - 知乎
相关参考链接:WPS JS宏的示例——项目阶段检测 - 知乎
相关参考 https://blog.csdn.net/u012735516/article/details/118163658