0


WPS JS宏入门案例集锦

JS宏官方API文档:https://qn.cache.wpscdn.cn/encs/doc/office_v19/index.htm

批量创建工作表/簿

批量创建工作表:

  1. function批量创建工作表(){for(var city of["成都","上海","北京"]){let sht = Worksheets.Add();
  2. sht.Name = city;}}

批量创建工作簿:

  1. function批量创建工作簿(){for(var city of["成都","上海","北京"]){
  2. book = Workbooks.Add();
  3. book.SaveAs(`E:/tmp/${city}`);
  4. book.Close();}}

若book.SaveAs不传入全路径,则默认可能保存到我的文档文件夹中。

批量拆分工作表到工作簿

数据如下:

image-20220928204354007

执行代码:

  1. function批量拆分工作表(){for(var sh of Sheets){// 如果既不指定 Before 也不指定 After,则新建一个工作簿,其中包含复制的工作表。
  2. sh.Copy();
  3. ActiveWorkbook.SaveAs(`E:/VBA/wps/${sh.Name}.xlsx`);
  4. ActiveWorkbook.Close();}}

分解出3个独立的文件:

image-20220928204807388

批量判断处理单元格数据

数据和需求如下:

image-20220928205227427

简单的方法就是直接筛选再复制粘贴,但是现在我们需要完全基于js宏的语法实现:

  1. function分数筛选(){var Arr1=[];var Arr2=Range("a2:b13").Value();for(var row of Arr2){if(row[1]>=100){
  2. Arr1.push(row);}}Range("d4").Resize(Arr1.length,2).Value2=Arr1
  3. }

运行后:

image-20220928205430277

工资条制作

数据如下:

image-20220928203156400

执行如下代码:

  1. function工资条制作(){
  2. Application.DisplayAlerts=false;let src=Sheets("工资表");for(let sht of Sheets){if(sht.Name=="结果") sht.Delete();}
  3. Application.DisplayAlerts=true;var sht=Worksheets.Add();
  4. sht.Name="结果";for(i=0;i<10;i++){
  5. src.Range("a1:m4").Copy();
  6. sht.Cells.Item(5*i+1,1).PasteSpecial();
  7. src.Range(`A${i+5}:M${i+5}`).Copy();
  8. sht.Cells.Item(5*i+5,1).PasteSpecial();}
  9. sht.Activate()}

拆分结果:

image-20220928203242283

注意:如果原表不止10人,则修改循环次数即可。

如果允许直接在原表上修改,可以使用相对引用录制宏得到代码:

  1. function工资条制作2(){Range("a1:m4").Select();for(var i=1;i<=9;i++){
  2. Selection.Copy();
  3. ActiveCell.Offset(5,0).Range("A1:M4").Insert(xlShiftDown,undefined);
  4. Application.CutCopyMode =false;
  5. ActiveCell.Offset(5,0).Range("A1:M4").Select();}}

任意多列SN号合并到一列

原数据都是如下格式的SN号:

image-20221005141323296

下面我们考虑通过宏代码合并到一列,代码如下:

  1. function单表多列合并到一列新文件(){var vs=Range("A1").CurrentRegion.Value().flat();// 过滤掉空值并去重
  2. vs=Array.from(newSet(vs.filter(v=>v!=undefined)));// 一维数组默认赋值给一行,赋值给一列需要先转置二维
  3. vs = WorksheetFunction.Transpose(vs);var wb = Workbooks.Add();
  4. wb.Sheets(1).Range("A1").Resize(vs.length,1).Value2 = vs;}

注意:上面的代码使用JavaScript的语法对数组进行了去重。

  1. Array.from(newSet(arr))

过滤空值:

  1. arr.filter(v=>v!=undefined)

最终得到一列:
在这里插入图片描述

批量合并工作表并添加来源表名

原数据:

image-20220928205804819

执行代码:

  1. function合并工作表数据(){var NewArr=[],n=1;for(var ws of Sheets){var Arr=ws.Range("a1").CurrentRegion.Value();if(n++==1){var title=Arr[0].concat("工作表名")};delete Arr[0]
  2. Arr.forEach(ar=>NewArr.push(ar.concat(ws.Name)));}
  3. NewArr.unshift(title);var wb=Workbooks.Add();
  4. wb.Sheets(1).Range("a1").Resize(NewArr.length,NewArr[0].length).Value2=NewArr;}

成功合并得到如下结果:

image-20220928210012195

语音朗读

代码如下:

  1. function Workbook_Open(){
  2. Application.Speech.Speak("美好的一天就从这一刻开始吧!",true)}
  3. function Workbook_NewSheet(Sh){
  4. Application.Speech.Speak("果然狠人老表,区区几张sheet是不够你消遣的!",true)}
  5. function Application_WorkbookBeforeClose(Wb, Cancel){
  6. Application.Speech.Speak("就想问老板,可以下班了吗?")}
  7. function Application_SheetSelectionChange(Sh, Target){if(Sh.Name!="词汇"|Target.Value()==undefined)return;
  8. Application.Speech.Speak(Target.Value());}

保存上面的代码后,当打开或关闭该文件或新建工作表都会朗读对应的文字。

对于词汇这张工作表,点击任何有值的单元格都会对其进行朗读。

  1. Application.Speech.Speak

第二个参数传入true表示异步,默认为同步。

富文本弹窗

alert函数支持传入HTML:

  1. functiontestAlert_CSS(){let foo =`
  2. <h3 style="color:red">Hi</h3>
  3. <p style="color:green;text-shadow: 1px 1px 2px red, 0 0 1em blue, 0 0 0.2em blue;">
  4. Hi ${newDate().toLocaleDateString()}
  5. </p>`;alert(foo)}

执行效果:

image-20220928210943115

判断目标是否在指定区域内

  1. function_m_isInArea(uArea,cell){
  2. uArea =typeof(uArea)=="string"?Range(uArea):uArea;
  3. cell =typeof(cell)=="string"?Range(cell):cell;if(uArea.Parent.Name!=cell.Parent.Name)returnfalse;let s_row=uArea.Row,e_row=s_row+uArea.Rows.Count-1;let s_col=uArea.Column,e_col=s_col+uArea.Columns.Count-1;let t_row = cell.Row,t_col = cell.Column;// Console.log(`${s_row}-${e_row},${s_col}-${e_col},(${t_row},${t_col})`);return s_row<=t_row && t_row<=e_row && s_col<=t_col && t_col<=e_col;}function_m_test(){
  4. Console.log(_m_isInArea("A2:C20","B3"));
  5. Console.log(_m_isInArea("A2:C20","D3"));}

结果:

  1. true
  2. false

本地文件读写

  1. functionread_write_data_txt(){let txtFile ="E:/tmp/a.txt";let f =FreeFile();Open(txtFile,f,jsOutput,jsWrite);Write(f,"123");Write(f,"456,789");Write(f,"aaa,bbb");Close();
  2. Console.clear()let fNumber =FreeFile()Open(txtFile, fNumber,jsInput)while(!EOF(fNumber)){let p=LineInput(fNumber);
  3. Console.log(p)}Close(fNumber)}
  1. "123"
  2. "456,789"
  3. "aaa,bbb"

生成文件:

image-20220928211451436

JavaScript语法补充

undefined和null的区别

undefined和null的区别(值相等,但类型不等) :

  1. typeofundefined// undefinedtypeofnull// objectnull===undefined// falsenull==undefined// true

typeof操作符

typeof 操作符可以检测变量的数据类型 :

  1. typeof"John"// 返回 string typeof3.14// 返回 numbertypeofNaN// 返回 numbertypeoffalse// 返回 booleantypeof[1,2,3,4]// 返回 objecttypeof{name:'John',age:34}// 返回 objecttypeofnewDate()// 返回 objecttypeoffunction(){}// 返回 functiontypeof myCar // 返回 undefined (如果 myCar 没有声明)typeofnull// 返回 object

解构赋值

  1. var[x, y, z]=['hello','JavaScript','ES6'];
  2. console.log('x = '+ x +', y = '+ y +', z = '+ z);// x = hello, y = JavaScript, z = ES6[x,[y, z]]=['hello',['JavaScript','ES6']];
  3. console.log('x = '+ x +', y = '+ y +', z = '+ z);// x = hello, y = JavaScript, z = ES6

数组常用方法

方法描述concat()连接两个或更多的数组,并返回结果。copyWithin()从数组的指定位置拷贝元素到数组的另一个指定位置中。entries()返回数组的可迭代对象。every()检测数值元素的每个元素是否都符合条件。fill()使用一个固定值来填充数组。filter()检测数值元素,并返回符合条件所有元素的数组。find()返回符合传入测试(函数)条件的数组元素。findIndex()返回符合传入测试(函数)条件的数组元素索引。forEach()数组每个元素都执行一次回调函数。from()通过给定的对象中创建一个数组。includes()判断一个数组是否包含一个指定的值。indexOf()搜索数组中的元素,并返回它所在的位置。isArray()判断对象是否为数组。join()把数组的所有元素放入一个字符串。keys()返回数组的可迭代对象,包含原始数组的键(key)。lastIndexOf()搜索数组中的元素,并返回它最后出现的位置。map()通过指定函数处理数组的每个元素,并返回处理后的数组。pop()删除数组的最后一个元素并返回删除的元素。push()向数组的末尾添加一个或更多元素,并返回新的长度。reduce()将数组元素计算为一个值(从左到右)。reduceRight()将数组元素计算为一个值(从右到左)。reverse()反转数组的元素顺序。shift()删除并返回数组的第一个元素。slice()选取数组的的一部分,并返回一个新数组。some()检测数组元素中是否有元素符合指定条件。sort()对数组的元素进行排序。splice()从数组中添加或删除元素。unshift()向数组的开头添加一个或更多元素,并返回新的长度。
splice:

  1. splice()

方法可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素:

  1. var arr =['Microsoft','Apple','Yahoo','AOL','Excite','Oracle'];// 从索引2开始删除3个元素,然后再添加两个元素:
  2. arr.splice(2,3,'Google','Facebook');// 返回删除的元素 ['Yahoo', 'AOL', 'Excite']
  3. arr;// ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']// 只删除,不添加:
  4. arr.splice(2,2);// ['Google', 'Facebook']
  5. arr;// ['Microsoft', 'Apple', 'Oracle']// 只添加,不删除:
  6. arr.splice(2,0,'Google','Facebook');// 返回[],因为没有删除任何元素
  7. arr;// ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']

concat:

  1. concat()

方法把当前的

  1. Array

和另一个

  1. Array

连接起来,并返回一个新的

  1. Array

  1. var arr =['A','B','C'];var added = arr.concat([1,2,3]);
  2. added;// ['A', 'B', 'C', 1, 2, 3]
  3. arr;// ['A', 'B', 'C']

请注意,

  1. concat()

方法并没有修改当前

  1. Array

,而是返回了一个新的

  1. Array

实际上,

  1. concat()

方法可以接收任意个元素和

  1. Array

,并且自动把

  1. Array

拆开,然后全部添加到新的

  1. Array

里:

  1. var arr =['A','B','C'];
  2. arr.concat(1,2,[3,4]);// ['A', 'B', 'C', 1, 2, 3, 4]

join:

  1. join()

方法把当前

  1. Array

的每个元素都用指定的字符串连接起来,然后返回连接后的字符串:

  1. var arr =['A','B','C',1,2,3];
  2. arr.join('-');// 'A-B-C-1-2-3'

如果

  1. Array

的元素不是字符串,将自动转换为字符串后再连接。

map函数遇到的问题

map的语法:

  1. array.map(function(currentValue,index,arr), thisValue)
  • currentValue: 当前元素的值
  • index : 当前元素的索引值
  • arr : 前元素属于的数组对象
  • thisValue:用作 “this” 的值。如果省略了 thisValue,或者传入 null、undefined,那么回调函数的 this 为全局对象。

利用

  1. map()

把字符串变成整数 :

  1. var arr =['1','2','3'];var r = arr.map(parseInt);
  2. console.log(r);//结果却是1, NaN, NaN

这是因为parseInt接受两个参数

  1. (string, radix)

,第二个参数指定被转换的“数字”多少进制。

  1. arr = [1,2,3]

时,

  1. arr.map(parseInt)

实际为:

  1. parseInt('1',0);// 按十进制转换'1'parseInt('2',1);// 按一进制转换'2',但一进制中只有0没有1parseInt('3',2);// 按二进制转换3,但二进制中只有0和1没有2

解决办法:

  1. var arr =['1','2','3'];var r = arr.map(str=>parseInt(str));
  2. console.log(r);// 结果:1,2,3

模板字符串

  1. var name ='小华';var age =20;var message =`你好, ${name}, 你今年${age}岁了!`;

循环语句

for循环

语法:

  1. for(语句 1; 语句 2; 语句 3){
  2. 被执行的代码块
  3. }
  • 语句1 (代码块)开始前执行
  • 语句2 定义运行循环(代码块)的条件
  • 语句3 在循环(代码块)已被执行之后执行
  1. for(var i=0,len=cars.length; i<len; i++){
  2. document.write(cars[i]+"<br>");}// 或var i=2,len=cars.length;for(; i<len; i++){
  3. document.write(cars[i]+"<br>");}

for…in循环

for/in 语句循环遍历对象的属性:

  1. var person={fname:"John",lname:"Doe",age:25};for(x in person)// x 为属性名{
  2. txt=txt + person[x];}

循环遍历

  1. Array

的索引:

  1. var a =['A','B','C'];for(var i in a){
  2. console.log(i);// '0', '1', '2'
  3. console.log(a[i]);// 'A', 'B', 'C'}

注意:

  1. for ... in

  1. Array

的循环得到的是

  1. String

而不是

  1. Number

for…of循环

具有

  1. iterable

类型的集合还可以通过

  1. for ... of

循环来遍历,它是ES6引入的新的语法。

  1. var a =['A','B','C'];var s =newSet(['A','B','C']);var m =newMap([[1,'x'],[2,'y'],[3,'z']]);for(var x of a){// 遍历Array
  2. console.log(x);}for(var x of s){// 遍历Set
  3. console.log(x);}for(var x of m){// 遍历Map
  4. console.log(x[0]+'='+ x[1]);}

  1. for of

循环和

  1. for in

循环的区别

  1. for ... in

循环遍历的实际是对象的属性名称,手动给Array对象添加了额外的属性后:

当我们手动给

  1. Array

对象添加了额外的属性后,

  1. for ... in

循环将带来意想不到的意外效果:

  1. var a =['A','B','C'];
  2. a.name ='Hello';for(var x in a){
  3. console.log(x);// '0', '1', '2', 'name'}
  1. for ... of

循环则只循环集合本身的元素:

  1. var a =['A','B','C'];
  2. a.name ='Hello';for(var x of a){
  3. console.log(x);// 'A', 'B', 'C'}

  1. iterable

内置的

  1. forEach

方法

  1. var a =['A','B','C'];
  2. a.forEach(function(element, index, array){// element: 指向当前元素的值// index: 指向当前索引// array: 指向Array对象本身
  3. console.log(element +', index = '+ index);});var s =newSet(['A','B','C']);//Set没有索引,因此回调函数的前两个参数都是元素本身
  4. s.forEach(function(element, sameElement,set){
  5. console.log(element);});var m =newMap([[1,'x'],[2,'y'],[3,'z']]);//Map的回调函数参数依次为value、key和map本身
  6. m.forEach(function(value, key, map){
  7. console.log(value);});

回调函数可以省略参数:

  1. var a =['A','B','C'];
  2. a.forEach(function(element){
  3. console.log(element);});

while 循环

语法:

  1. while(条件){
  2. 需要执行的代码
  3. }// 或do{
  4. 需要执行的代码
  5. }while(条件);

例子:

  1. while(i<5){
  2. x=x +"The number is "+ i +"<br>";
  3. i++;}do{
  4. x=x +"The number is "+ i +"<br>";
  5. i++;}while(i<5);

箭头函数与装饰器

ES6 新增了箭头函数,语法 :

  1. (参数1, 参数2, …, 参数N)=>{ 函数声明 }单一参数=>{函数声明}()=>{函数声明}

例子:

  1. constx=(x, y)=> x * y;constx=(x, y)=>{return x * y };

箭头函数简化了函数定义,如果只包含一个表达式,可以省略

  1. { ... }

  1. return

如果要返回一个对象,单表达式会报错:

  1. // SyntaxError:x=>{foo: x }

因为和函数体的

  1. { ... }

有语法冲突,所以要改为:

  1. // ok:x=>({foo: x })

箭头函数看上去是匿名函数的一种简写,但有个明显的区别:箭头函数内部的

  1. this

是词法作用域,由上下文确定。

箭头函数的

  1. this

总是指向词法作用域,也就是外层调用者

  1. obj

  1. var obj ={birth:1990,getAge:function(){var b =this.birth;// 1990varfn=()=>newDate().getFullYear()-this.birth;// this指向obj对象returnfn();}};
  2. obj.getAge();// 25

由于

  1. this

在箭头函数中已经按照词法作用域绑定了,所以,用

  1. call()

或者

  1. apply()

调用箭头函数时,无法对

  1. this

进行绑定,即传入的第一个参数被忽略:

  1. var obj ={birth:2000,getAge:function(year){var b =this.birth;// 1990varfn=(y)=> y -this.birth;// this.birth仍是2000returnfn.call({birth:2010}, year);}};
  2. obj.getAge(2015);// 15

在一个独立的函数调用中,根据是否是strict模式,

  1. this

指向

  1. undefined

  1. window

要指定函数的

  1. this

指向哪个对象,可以用函数本身的

  1. apply

方法,它接收两个参数,第一个参数就是需要绑定的

  1. this

变量,第二个参数是

  1. Array

,表示函数本身的参数。

  1. apply

修复

  1. getAge()

调用:

  1. functiongetAge(){var y =newDate().getFullYear();return y -this.birth;}var xiaoming ={name:'小明',birth:1990,age: getAge
  2. };
  3. xiaoming.age();// 25getAge.apply(xiaoming,[]);// 25, this指向xiaoming, 参数为空

利用

  1. apply()

可实现装饰器,比如想统计一下代码一共调用了多少次:

  1. 'use strict';var count =0;var oldParseInt = parseInt;// 保存原函数
  2. window.parseInt=function(){
  3. count +=1;returnoldParseInt.apply(null, arguments);// 调用原函数};parseInt('10');parseInt('20');parseInt('30');
  4. console.log('count = '+ count);// 3
  1. call()

  1. apply()

类似,唯一区别是:

  • apply()把参数打包成Array再传入;
  • call()把参数按顺序传入。

比如调用

  1. Math.max(3, 5, 4)

,分别用

  1. apply()

  1. call()

实现如下:

  1. Math.max.apply(null,[3,5,4]);// 5
  2. Math.max.call(null,3,5,4);// 5

对普通函数调用,通常把

  1. this

绑定为

  1. null

标签: javascript 前端 html

本文转载自: https://blog.csdn.net/as604049322/article/details/127097880
版权归原作者 小小明-代码实体 所有, 如有侵权,请联系我们删除。

“WPS JS宏入门案例集锦”的评论:

还没有评论