mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-16 22:23:45 +08:00
mod
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
<audio id="audio" title="12|文本处理函数:三招解决数据对齐问题" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/54/1f/54f16a2a9e74a8a9b3f58b901211cd1f.mp3"></audio>
|
||||
|
||||
你好,我是尹会生。
|
||||
|
||||
当你在工作中利用Excel向同事展示业务数据时,肯定遇到过数据无法对齐的问题。
|
||||
|
||||
比如在展示日销售额报表数据时,如果数字、日期、文字这些常见的元素没有对齐,你不仅会因为格式显示混乱而难以分析数据变化的趋势,而且也会因为报表格式不够工整,给领导留下一个技术能力不扎实的不良印象。
|
||||
|
||||
而且,如果一个个手动来调整格式,不仅麻烦,而且还很容易出错。那么今天这节课,我就教你怎样用Python的文本处理函数,利用format()、split()、join()和strip()四个函数来对Excel中的数字、日期和文字进行长度调整和移除多余空格等处理,解决数据对齐问题。
|
||||
|
||||
## 数据对齐的思路
|
||||
|
||||
为了更好地掌握Python的文本处理函数,我先带你了解Excel中数据的默认对齐方式,以及需要使用Python中的哪些文本函数。
|
||||
|
||||
Excel中的数据是有默认对齐方式的,对齐的方式一共有三种,分别是右对齐、左对齐和居中对齐。数据类型不同,默认对齐方式也不同。
|
||||
|
||||
- 数值型数据会自动靠右对齐,比如日期、时间、数字。
|
||||
- 文本型数据会自动靠左对齐,比如汉字、字母、英文、引号开头的数字。
|
||||
|
||||
当你把数据粘贴到Excel中时,如果是同类型数据没有实现对齐,你就要考虑在粘贴到Excel之前对数据进行处理。
|
||||
|
||||
具体怎么处理呢?我们可以根据Excel的默认对齐方式,以及导入到Excel中的内容,来分情况考虑。
|
||||
|
||||
在右对齐的类型中,数字、日期、时间是我们接触最多的数值类型,而数字和日期、时间的处理方式又有差别,所以我们要分开来学习和掌握它们。
|
||||
|
||||
在左对齐的类型中,文字、字母、英文和引号开头的数字,它们的对齐方式相同,都是去掉前方的空格。所以在你掌握文字前后的空格处理之后,就可以举一反三地对其他三种数据类型实现左侧对齐。
|
||||
|
||||
还有最后一种对齐方式是居中对齐。居中对齐的场景只有一种,那就是作为主题使用。这种对齐方式可以直接通过手动操作来完成。
|
||||
|
||||
因此,我通过对数字、日期、文字三种类型的处理,可以让你应对大多数数据对齐的场景了。总结来说,那就是:
|
||||
|
||||
- 采用format()函数,实现数字对齐;
|
||||
- 使用split()和join()函数,实现日期右侧对齐;
|
||||
- 使用strip() 函数,实现文本型数据的左侧对齐。
|
||||
|
||||
接下来我就详细讲解一下这三种解决方法。
|
||||
|
||||
## 数据对齐的办法
|
||||
|
||||
#### 第一招 使用format()函数,实现数字对齐
|
||||
|
||||
数字没有对齐,主要是因为数字位数不同。所以我们可以通过补全数字位数的方法,来对齐数字。
|
||||
|
||||
我们来看一个例子。在这个例子中,我提供了5个浮点数,它们的内容和格式如下:
|
||||
|
||||
```
|
||||
12.34
|
||||
123.456
|
||||
1.2345
|
||||
123456.78
|
||||
123.4
|
||||
|
||||
```
|
||||
|
||||
在这组浮点数中,它们各自的小数位数也不同。如果直接粘贴到Excel,会因为小数位数不同而无法直观地比较它们的大小。
|
||||
|
||||
在这种情况下,你可以使用Python的内置format()函数,把它们都保留至小数点后四位,这样既能保证每个浮点数的精度,又能按右侧对齐小数点。
|
||||
|
||||
那我对这5个浮点统一使用format()函数进行处理,它的代码是:
|
||||
|
||||
```
|
||||
string1 = 123.45
|
||||
print("{:.4f}".format(string1))
|
||||
# 123.4500
|
||||
|
||||
```
|
||||
|
||||
这段代码把“123.45”使用format()函数进行格式处理后,就会保留小数点后四位,输出“123.4500”。所以如果把浮点数用format()函数进行处理,再粘贴到Excel中,就可以实现自动右侧对齐了。
|
||||
|
||||
那我们接下来就学习一下format()函数的**调用方式和格式,看**format()函数是怎么**来补齐<strong><strong>数字小数的位数**</strong>,并且调整**<strong>整数**</strong>的**<strong>位置**</strong>的。</strong>
|
||||
|
||||
format()函数是Python的2.6版本新增的内置函数,它增强了字符串的格式处理功能。你应该想到了,format()函数是内置函数,所以它和我们之前学习过的print()、int()、str()函数一样,可以在Python中直接调用,不用预先定义和import导入。
|
||||
|
||||
使用format()函数对数字格式调整时,调用format()的Python语句是“{:数字的格式}.format(要转换格式的数字)”,在这条语句里,“:”后面的**数字的格式包含**三个部分。
|
||||
|
||||
第一部分表示符号和空格,可以使用+、-、(空格)。
|
||||
|
||||
- “+”表示在正数前显示 +;
|
||||
- “-”表示负数前显示 -;
|
||||
- (空格)表示在正数前加空格。
|
||||
|
||||
第二部分表示宽度,可以使用. < > ^, “.”来保留小数点后的位数。
|
||||
|
||||
- .4表示保留小数点后四位;
|
||||
- ^, <, > 分别是居中、左对齐、右对齐,后面也需要使用数字指定宽度,如果不满足宽度自动补充空格。
|
||||
|
||||
第三部分表示类型,常见的有“b、d、f”,分别表示二进制、十进制和浮点数。比如我可以使用如下代码,来表示整数100占用6个字符的宽度,并靠右侧对齐。
|
||||
|
||||
```
|
||||
print("{:6>d}".format(100))
|
||||
#执行结果
|
||||
(空格)(空格)(空格)100
|
||||
|
||||
```
|
||||
|
||||
可以看到,format()函数有着非常丰富的参数,除了可以进行数字对齐外,还可以调整字符串格式,所以我也经常用format()函数在工作中进行格式化字符串操作。不过这些参数和数字对齐的关系不大,我在这节课就不把它们一一列出来了,如果你想详细了解,可以参考[官方文档](https://docs.python.org/zh-cn/3.7/library/string.html#formatspec)。
|
||||
|
||||
接下来我们来看一下如果是日期类型,怎么使用字符串函数实现它的右侧对齐。
|
||||
|
||||
#### 第二招 使用字符串函数,实现日期右侧对齐
|
||||
|
||||
日期对齐和数字对齐相比,最主要的区别就是它的年、月、日三个部分都可能出现不等长的情况。我给你举个例子,你一看就明白了。
|
||||
|
||||
```
|
||||
2021-3-18
|
||||
21-3-18
|
||||
2021-12-21
|
||||
2021-3-18
|
||||
21-3-1
|
||||
|
||||
```
|
||||
|
||||
在这5个日期中,由于年、月、日的位数不同,导致粘贴到Excel后没法实现右侧对齐。因此我们实现日期对齐的前提,就是要补齐日期。而补齐日期的过程,我们需要按照**先<strong><strong>拆分日期**</strong>、再**<strong>调整格式**</strong>、最后合并日期</strong>的顺序。
|
||||
|
||||
我先把它的代码写出来,供你参考,然后再给你讲解补齐日期的过程。
|
||||
|
||||
```
|
||||
date_demo = [
|
||||
"2021-03-18",
|
||||
"21-3-18",
|
||||
"2021-12-21",
|
||||
"2021-3-8",
|
||||
"21-3-1",
|
||||
]
|
||||
|
||||
for dd in date_demo:
|
||||
# 拆分日期
|
||||
year, month, day = dd.split('-')
|
||||
# 调整格式
|
||||
if len(year)== 2 :
|
||||
new_year = 2021
|
||||
else:
|
||||
new_year = year
|
||||
|
||||
month = "{:>02d}".format(int(month))
|
||||
day = "{:>02d}".format(int(day))
|
||||
# 合并日期
|
||||
new_date = [str(new_year), str(month), str(day)]
|
||||
new_date = "-".join(new_date)
|
||||
|
||||
print(new_date)
|
||||
|
||||
# 执行结果
|
||||
2021-03-18
|
||||
2021-03-18
|
||||
2021-12-21
|
||||
2021-03-08
|
||||
2021-03-01
|
||||
|
||||
|
||||
```
|
||||
|
||||
通过这段代码的执行结果,可以看到我把长度不同的5个日期,按照年、月、日三个部分别进行了长度处理,并使用“-”作为日期分隔符,从而实现日期的等长。
|
||||
|
||||
接下来,我按照程序的执行顺序,为你详细讲解一下我是怎么对日期进行**拆分、调整和合并**的。
|
||||
|
||||
为什么要先进行拆分这一操作呢?因为在我们已知的函数中,没法对年、月、日分别进行调整。如果整体进行调整,比如调整年,很容易影响到月和日的数字,我把它称作**调整的副作用**。所以我就需要通过split()函数先对完整日期进行拆分。
|
||||
|
||||
split()函数是我们这节课要重点掌握的一个函数,我来为你讲解一下它的主要用法。
|
||||
|
||||
按照学习其他函数的经验,你需要掌握split()函数的功能、参数和返回值。实际上对于所有函数的学习,我们都需要先关注函数功能、参数个数和类型、返回值个数和类型三个部分,之后再去学习参数函数里的业务逻辑功能。这其实也是掌握函数的通用做法。
|
||||
|
||||
split()函数是对字符串进行拆分的函数,也是根据字符串中指定的分隔符,它的参数“-”就是拆分字符串的分隔符,它的返回值是拆分以后字符串形成的列表。
|
||||
|
||||
我在返回值中使用了连续赋值的功能,那么就可以通过以下代码来实现:
|
||||
|
||||
```
|
||||
year, month, day = dd.split('-')
|
||||
|
||||
```
|
||||
|
||||
这种方式,让变量year、month、day依次得到了列表中的三个元素。
|
||||
|
||||
由于在代码的后续运行过程中,我需要对每个变量进行单独处理,而使用列表还需要通过下标访问每个列表。那么这里我就用三个变量代替列表来作为split()函数的返回值。不过我用变量代替列表还有一个原因,那就是在代码的阅读上,使用变量方式更易于理解。
|
||||
|
||||
接下来是调整内容阶段,我依然使用format()函数对日期的每个部分进行长度上的调整。你可以通过代码来学习,如何使用format进行日期的每个部分调整的。
|
||||
|
||||
最后,我把调整好的年、月、日,使用join()函数进行合并。为了和原始字符串保持一致,我继续使用“-”作为连接符号,对函数的参数new_date列表进行连接。而且,join()函数返回的类型是字符串,刚好和处理之前的类型保持一致,如果你的代码里包含了对日期进行操作的功能,调整长度后这些代码就可以保持不变。
|
||||
|
||||
此外,这里还有两点需要你注意:
|
||||
|
||||
1. 工作中经常会遇到一个字符串中多处需要修改的内容,例如刚才举的日期例子,你可以把split()和join()函数配合使用,拆分成多个变量,对变量进行处理后,再进行合并,减少处理的复杂度。
|
||||
1. 在使用split()前,你还可以通过正则表达式来处理不规范的分隔符,让字符串每个字段都能按照相同的分隔符进行拆分。
|
||||
|
||||
#### 第三招 使用字符串函数,实现文本型数据的对齐
|
||||
|
||||
Excel中的文字默认是左侧对齐,那文字类型为什么会出现没法对齐的情况呢?主要是因为文字在开头或结尾包含了一个或多个空格。
|
||||
|
||||
对于这些空格,可以使用字符串自带的strip()函数来去掉。我把删除文字前后空格的代码写在下方,供你参考:
|
||||
|
||||
```
|
||||
string = " 广东省广州市 "
|
||||
newstring = string.strip()
|
||||
print(f"|{newstring}|")
|
||||
|
||||
# 输出结果
|
||||
|广东省广州市|
|
||||
|
||||
```
|
||||
|
||||
在这段代码中,我通过内置的strip()函数,去掉了字符串前后的空格,并通过f-string调整了字符串的格式。
|
||||
|
||||
strip()函数是我们这节课新学习的函数,它的主要功能就是自动移除字符串开头和结尾指定的字符,如果没有为strip()函数指定参数,默认会移除字符串开头和结尾连续的多个空格。
|
||||
|
||||
另一个新学习的函数是f-string,我在代码的第三行使用了它,用于调整newstring字符串的输出结果。f-string是在Python3.6版本引入的一种新的字符串,它的写法是在字符串前增加f关键字,增加后我们就能在一般的字符串中使用“{}”关键字,“{}”中允许使用变量、运算以及和format()相同的格式描述符。
|
||||
|
||||
为了让你更直观地看到空格是不是被移除掉了,我还利用f-string在newstring字符串前后增加了“|”,这里可以用任意一个字符,主要用于观察竖线和文字间是否有空格。这样你通过结果,就可以看到“|”和“ 广东省广州市 ”前后的空格已经被自动删除掉了。
|
||||
|
||||
可以看到,f-string和format()函数都具有对字符串输出格式调整的功能,不过前者更适用于**字符串和变量连接**的场景,后者更适用于调整字符串的格式。此外,f-string除了可以用来观察文字对齐的结果外,你还可以在输出变量的同时也输出字符串。
|
||||
|
||||
## **小结**
|
||||
|
||||
最后,我来为你总结一下这节课的核心内容。今天这节课我们主要讲了四个字符串处理函数,它们也是文本处理工作中最经常用到的函数:
|
||||
|
||||
1. format()函数,可以对字符串或数字进行格式化,对浮点数的小数位数进行调整,实现小数的对齐。
|
||||
1. split()函数,按指定的分隔符分隔字段,实现字符串中的部分字符串处理。
|
||||
1. join()函数,能够将列表、元组中的每个元素按照指定的分隔符连接成字符串,如果是字符串和变量的连接,你还可以使用f-sring方式实现字符串连接功能。
|
||||
1. strip()函数,它是自动去掉字符串前后空格的函数,经常用于从文本提取内容后,对文本前后空格进行删除,优化文字内容显示结果的函数。
|
||||
|
||||
我把今天这节课用到的[代码](https://github.com/wilsonyin123/python_productivity/blob/main/%E6%96%87%E7%AB%A012%E4%BB%A3%E7%A0%81.zip)都放在了GitHub上,文稿里也有链接,你可以去学习掌握。
|
||||
|
||||
## **思考题**
|
||||
|
||||
按照惯例,最后我来为你留一道思考题。如果你需要将文本文件中的“小时:分钟:秒”处理成等长格式,再存入Excel中,你需要使用哪些函数做怎样的处理,才能实现时间的对齐呢?
|
||||
|
||||
欢迎把你的思考和想法写在评论区,我们一起交流讨论。此外,你还可以扫描课程详情页的二维码,加入我们的课程读者群,我也会在群里为你解疑答惑。
|
||||
@@ -0,0 +1,179 @@
|
||||
<audio id="audio" title="13|Excel插件:如何扩展Excel的基本功能?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/4a/ac/4ac0e3a5915d52b5289ff62d503e32ac.mp3"></audio>
|
||||
|
||||
你好,我是尹会生。
|
||||
|
||||
我们在讲了怎么利用Python优化Excel的输入和计算效率之后,相信你已经知道该怎么使用Python的循环和文件库进行多个文件的处理,怎么使用正则表达式对内容进行查找和替换。
|
||||
|
||||
但是有时会因为临时的需求,为了得到查询的结果而进行一次性的表格处理,这时候如果用Python来解决,估计你有一种“杀鸡用牛刀”的感觉,未免小题大做了。
|
||||
|
||||
所以在接下来的三节课里,我会利用Excel中自带的插件和更简单的两个脚本工具,来完成这种临时的、简单的重复性任务,让你用更便捷的方式实现办公自动化。
|
||||
|
||||
今天这节课呢,我就给你介绍一个在Excel中非常著名的Power Query插件,利用这个插件你可以完成我们经常遇到的数据清理工作。
|
||||
|
||||
## Power Query的主要用途
|
||||
|
||||
我先来介绍一下Power Query这个插件。从它的名字,你应该就能猜到它的主要用途,那就是**在查询方面对Excel进行优化。**
|
||||
|
||||
**我所说的**查询优化是泛指,它的涵盖范围比较广。为了方便使用Excel统计数据,往往需要在统计数据前去调整Excel表格的格式、内容以及字段类型,这些在Excel中统称为**查询操作。**
|
||||
|
||||
如果能够把新增数据自动更新到已经处理的数据中,还能自动化地按照之前的操作步骤对表格中的数据进行调整,这就是Power Query比手动调整Excel更有效率的地方**。**
|
||||
|
||||
在查询大量数据中,最耗时的就是清理数据工作了,具体来说,就是把需要统计的数据从多个文件进行提取和合并,把不符合统计格式的数据进行自动化处理,最终形成符合数据统计的规范格式。
|
||||
|
||||
比如:数据被存储到多个文件里,而你需要把多个文件的内容手动合并到一个Excel中。再比如:Excel中的日期包含了年月日和具体时间,如果要按日期汇总这些数据,那你就需要先把年月日和时间拆分。不方便的是,如果表格里的数据更新了,你就必须要重新再手动拆分一遍。
|
||||
|
||||
其实这两个例子,代表了清理数据工作中需要自动化最典型的两个场景,那就是**文件导入和格式调整**。而Power Query 就是优化这两个主要功能的插件。
|
||||
|
||||
那怎么用Power Query来优化呢?你需要掌握三个主要步骤,分别是**获取数据、转换<strong><strong>和**</strong>加载</strong>。只要是用Power Query来优化Excel的查询,这三个步骤是必须要掌握的。我也再来具体解释一下每个步骤的具体操作。
|
||||
|
||||
**获取数据,<strong><strong>指的是把**</strong>数据传入Power Query 的过程</strong>。通常我们会新建一个工作簿,把Excel打开之后,然后再切换到“数据”选项卡。接着,单击“获取数据”按钮,在下拉菜单中选择“自文件”命令,继续在下一级菜单中选择“从文件夹”命令,通过弹出的“文件夹”对话框,就可以加载文件夹中的所有Excel文件了。具体操作示范如下图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d4/b9/d44bd77930eebecc9f5efc5a273b90b9.png" alt="">
|
||||
|
||||
转换,指的是对数据的清理工作。在这一步,你需要把你加载到Power Query中的数据从文件到sheet,再从sheet到行列依次处理,对合并好的数据再进行添加、删除列、筛选、添加自定义计算等操作。
|
||||
|
||||
这一步是把不符合统计需求的数据调整为符合统计需求数据的最主要操作步骤,也是最繁琐的一步。例如把销售代表字段拆分成姓氏和名字,将订单日期的时间字段去掉,就可以使用转换这一操作来完成。
|
||||
|
||||
我给你画一幅图,用来帮你直观理解转换前后的变化,图片如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/80/3f/803f330abe1cd26244e2e446aefe043f.png" alt="">
|
||||
|
||||
第三步是加载,指的是把已经清理和转换的数据返回到Excel中。这一步比较简单,这里我就不多讲了。
|
||||
|
||||
讲完了用Power Query优化Excel查询的三个核心步骤,那接下来我就用两个典型案例,来,带你实践一下具体的操作。
|
||||
|
||||
## 如何用Power Query优化Excel的查询
|
||||
|
||||
我选用了两个不同的案例,覆盖了我在第一部分所说的文件导入和格式调整这两种最经常需要手动操作的场景,这两个场景就是:
|
||||
|
||||
1. 把多个文件合并到一个Excel中;
|
||||
1. 把单元格内容调整为统一格式。
|
||||
|
||||
那么接下来,我就教你怎么使用Power Query加快手工操作Excel的效率。
|
||||
|
||||
### 把多个文件合并成一个Excel
|
||||
|
||||
把多个文件合并成一个Excel表格,是处理大量数据的先决条件。那么涉及到处理大量数据的工作,都要进行合并这一步操作。
|
||||
|
||||
像是数据被分成多个文件,每个文件里有多个表的情况,在工作中非常常见。如果数据是按月、按天分成不同的工作簿,合并它们是一件更麻烦的事情。
|
||||
|
||||
接下来我就以半年的销售数据表格为例,分7个步骤,来讲解怎么使用Power Query实现多个Excel文件的合并功能。
|
||||
|
||||
**第一步,获取数据**。
|
||||
|
||||
通过Excel的“数据选项卡”-“获取数据”-“自文件”-“从文件夹”命令,会弹出一个对话框。此时,你可以选中需要合并的文件夹,这样该文件夹内的所有文件都会被识别出来。
|
||||
|
||||
由于每个文件中可能会有不同的表,不能把它们直接合并。因此,我们需要点击“编辑”按钮,进入Power Query编辑界面。
|
||||
|
||||
这个界面是Power Query 的主要工作界面,在你需要对多个文件进行自动化批量修改时,都需要通过这个界面来完成操作。同时,这个界面也会把你操作的中间结果显示出来。
|
||||
|
||||
我们来从左到右依次看一下界面的内容。由于Power Query的界面较大,我先把左侧和中间的界面放在下图:<br>
|
||||
<img src="https://static001.geekbang.org/resource/image/08/3d/0819a366e23ec8d41d9d8b48105efd3d.png" alt="">
|
||||
|
||||
界面的中间会显示导入的文件名称和数量,文件的内容会保存在Content列中。
|
||||
|
||||
另外,我要提醒一下,你还应该关注**左侧和右侧的提示信息**。左侧会显示你进行的多次清理操作,每次清理被称作查询。查询的名字可以在右侧的“查询设置”里进行名称修改,右侧的“应用的步骤”列表还能记录操作历史,如果你认为处理结果不符合期望,那就可以返回上一步,重新调整查询结果。
|
||||
|
||||
我把右侧的名称和步骤也贴在下方,供你参考。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/68/fc/688724de2febe3f2f39fc6bcd90f7efc.png" alt="">
|
||||
|
||||
第二步,我们需要把工作簿中的数据从Content列中解析出来,并且添加在现有内容的右侧。
|
||||
|
||||
在这里,我们可以使用一个公式来添加新的列。你需要切换到“添加列”选项卡,单击“自定义列”按钮,然后在弹出的对话框中**输入公式“Excel.Workbook([Content],true)** ”, 最后点击确定。
|
||||
|
||||
我把添加自定义列的操作图片也放在下方。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/47/21/47a55b6a3b55e87719cbb31508e66621.png" alt="">
|
||||
|
||||
可以看到,通过自定义列的功能,你将会在原有表格的基础上再添加新的一列,而这一列的内容是Table,表示文件中所有的表格内容。这里有一点你需要注意的,那就是自定义列的公式需要区分大小写。
|
||||
|
||||
**第三步,<strong><strong>调整每个sheet的每一行**</strong>。</strong>
|
||||
|
||||
你需要点击第二步添加“自定义”列右侧的数据展开按钮,然后取消勾选“使用原始列名作为前缀”复选框,并点击确定。如图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/cc/0f/ccaef51292b0137345ee68d53aa91c0f.png" alt="">
|
||||
|
||||
**第四步,在调整完行之后,你还需要调整每个文件中要查询的sheet和列,**它们也是以复选框的形式为你展示的。
|
||||
|
||||
例如我在每个文件只使用了一个sheet,每个sheet中的所有列都需要进行查询,所以我就可以选中所有的sheet和列。我把操作截图贴在下面方便你学习。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a4/cd/a47c30da66798a9dc8d03e943bc28acd.png" alt="">
|
||||
|
||||
选择指定的sheet功能,你可以点击Item列右侧的下拉菜单,勾选需要的sheet。点击确定之后,Power Query编辑器界面就会产生新的列,即“Data”列。
|
||||
|
||||
Data列保存了我们在第二步选中的sheet的所有表格,在我们今天的案例中,由于我需要所有的列,因此我就“选择所有列”,并点击“确定”按钮,展开Data列,这样就得到了我需要查询的数据。
|
||||
|
||||
第五步,通过上面四个步骤,就可以把所有数据按照你需要的sheet、行、列,导入到Power Query编辑器了。不过这时编辑器界面还有要处理的中间数据,因此我可以通过删除其他列的方式,来删除额外的数据。
|
||||
|
||||
具体做法是:使用主页选项卡的“删除列”下拉列表,选择“删除其他列”。我把删除前后的截图贴在下方,供你参考。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/af/yy/af3f5251248eee7f7b1441f5ac40a8yy.png" alt=""><img src="https://static001.geekbang.org/resource/image/4b/e0/4bfda71f6b10cdb58c1cf00591fb50e0.png" alt="">
|
||||
|
||||
第六步,由于处理完数据内容后,Excel的每一列类型会自动变成文本类型,导致最终执行结果显示错误,所以我们还需要继续修改类型。可以看到,我把“订单日期”改为日期时间类型,把销售额改为小数类型。具体修改方式是点击列标题前的类型图标,通过弹出的下拉列表,选择指定的类型,如图所示:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/92/ec/92dc79ed1443891514c9788817c492ec.png" alt="">
|
||||
|
||||
第七步,也是最后一步。我把编辑器的数据保存回Excel中,点击“主页”选项卡上的关闭并下载,这样就实现了把多个文件合并到一个Excel的功能。
|
||||
|
||||
通过这个例子,我把Power Query的三个主要处理步骤:获取数据、转换和加载,分解成了具体的七个操作步骤,来编写Power Query的主要流程。这七个步骤其实并不繁琐,并且你要是再细心点儿,就会发现我是把“转换”这一部分拆解成了五个步骤,其他两部分并没有变。
|
||||
|
||||
总结来说,相比较Python,Power Query不需要编程就能实现多个文件的合并,操作也更加简单。而且在每一步操作之后,你还能通过图形界面及时观察每一步骤的执行结果,这要比Python更加直观,也比Python更适用于一次性的多文件合并场景。
|
||||
|
||||
Power Query不但在获取数据的时候可以实现自动化查询功能,而且在单元格的转换和添加列上,也能实现自动化查询功能。那么接下来我就以拆分列功能为例,给你演示一下Power Query的转换功能是如何实现自动化查询的。
|
||||
|
||||
### 单元格的拆分
|
||||
|
||||
拆分列,是自动化查询转换功能时最常用到的选项。例如你在按日期汇总数据时,发现日期这列除了年月日,还包括时间信息,这样就没法按照相同的年月日进行合并,而必须要先对日期单元格进行拆分,拆分之后才能按照年月日这一列汇总数据。
|
||||
|
||||
还有,当你需要对销售人员的姓氏、名字分别处理时,也要按照字数对姓名单元格拆开,然后分别处理。
|
||||
|
||||
拆分的功能在Excel中也是可以实现的,但是Power Query能够在拆分之后,对新导入的文件也能通过点击刷新实现自动拆分。那么接下来我就教你怎样在Power Query里,使用拆分列功能来拆分日期时间和姓名,并在增加文件后实现自动更新。
|
||||
|
||||
首先,我们需要再次打开Power Query编辑器。你可以在Excel的数据选项卡,通过“获取数据”下拉列表,选择“启动Power Query编辑器”。
|
||||
|
||||
其次,你需要在Power Query编辑器,选中“转换”选项卡。通过选中“dt_订单日期”列,使用拆分列下拉列表的“按分隔符拆分”按钮,把分隔符改为空格后,再点击确定,这样就可以把订单日期拆分为两个新的列。
|
||||
|
||||
最后,删除“小时”这一列后,订单日期就实现了拆分功能。
|
||||
|
||||
你看,通过对不必要信息的拆分删除,就可以对列的内容进行自动化调整了。
|
||||
|
||||
这里我也再补充一点,除了“按分隔符拆分”外,你还可以按字的个数进行拆分。例如,我把销售代表的“姓名”进行拆分,你可以使用“按字符数拆分列”选项,如下图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fc/18/fc7ff3c3dc0b40507e4b44faf3630218.png" alt="">
|
||||
|
||||
通过这张图就可以看到,我通过调整字符数和拆分次数,就把“姓”和“名字”进行了拆分。拆分后的结果如下图,供你参考。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a9/dc/a9a23ed5d479400285146a2488382cdc.png" alt="">
|
||||
|
||||
总结来说,通过日期的拆分,你可以自动化移除字符串中不必要的内容。而通过对姓名的拆分,你可以在后续操作中分别对姓名进行处理。
|
||||
|
||||
不过,如果后续有了新的文件,那该怎么在当前执行结果上,再把新的文件进行自动拆分呢?
|
||||
|
||||
具体做法是:你可以在存放半年销售数据的文件夹中,直接放入下一个月的销售数据。只要原始的Excel文件格式和之前的6个文件相同,那么当你点击“刷新”按钮后,Power Query就会自动加载新的Excel文件,并自动把新的数据中的姓名、日期进行拆分。
|
||||
|
||||
这样就能实现自动查询的功能,不用重复执行获取数据和转换功能,也大大提高了数据的处理效率。
|
||||
|
||||
### 其他功能怎样学习
|
||||
|
||||
我利用了文件合并和单元格拆分,为你演示了Power Query的工作过程和常见功能。不过Power Query在自动化查询工作中,还能实现非常丰富的“转换”、“添加列”功能,他们分别在转换和添加列选项卡下,如果你需要掌握更多的功能,可以参考[官方文档](https://docs.microsoft.com/zh-cn/power-query/)进行学习。
|
||||
|
||||
### 小结
|
||||
|
||||
在这节课中,我使用Power Query实现了多个文件的合并,以及单元格的拆分处理,为你演示了它的自动化查询功能。
|
||||
|
||||
如果你跟着操作下来,就会发现,Power Query使用了图形界面,比Python处理数据更直观。通过Power Query编辑器,你可以一边观察处理结果,一边调整处理的功能。它的自动化体现在增加新的输入源或新的列,通过“刷新”功能,都能自动化识别和按照执行过的步骤对新增内容进行自动化处理。
|
||||
|
||||
此外,Power Query除了使用界面外,还支持脚本语言,也叫M语言。通过M语言,Power Query可以实现功能更丰富的转换和添加列功能,M语言也有函数、判断和循环逻辑等脚本语言的语法,在你掌握Python之后,学习它就更加轻松了。
|
||||
|
||||
总结来说,Power Query弥补了工作中处理一次性需求的短板,它比Excel更自动化,比Python更简单,为自动化查询工作提供了高效的解决方案。
|
||||
|
||||
我把这节课用到的Excel作为附件放在下方,你可以点击下载。
|
||||
|
||||
[合并文件到Excel.rar](https://uploader.shimo.im/f/PIdwahWcGeQracS8.rar)
|
||||
|
||||
### 思考题
|
||||
|
||||
最后,我给你留一道思考题:如何在Power Query编辑器中实现统计每个月的销售额,以及如何实现每种产品名称半年的销售额统计功能。
|
||||
|
||||
欢迎把你的思考和想法写在评论区,我们一起交流讨论。此外,你还可以点击课程详情页的“戳我进群”,扫描二维码,加入我们的课程读者群,我也会在群里为你解疑答惑。
|
||||
@@ -0,0 +1,197 @@
|
||||
<audio id="audio" title="14|VBA脚本编程:如何扩展Excel,实现文件的批量打印?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/88/3e/88227dc0ce0bdee2c6b358433c8f743e.mp3"></audio>
|
||||
|
||||
你好,我是尹会生。
|
||||
|
||||
打印,是办公中必不可少的一步,比如在会议上,我们需要通过Excel表格向客户/领导展示工作成果。
|
||||
|
||||
但在使用Python对Excel进行打印的时候,我们还得给Python安装上Excel、Windows和硬件设备管理的库,过程极其复杂,远远达不到我们自动化办公的需要。尤其是面对类似的临时性需求,就更没必要使用Python了。
|
||||
|
||||
庆幸的是,Excel自带了打印功能,而我们可以利用Excel的扩展——“宏”来实现打印,并且通过VBA脚本增强“宏”的功能,从而实现批量打印,满足我们自动化办公的要求。
|
||||
|
||||
那么在今天这节课,我就带着你学习Excel的另一个自动化功能:“宏”和VBA脚本。
|
||||
|
||||
### 宏和VBA脚本的用途
|
||||
|
||||
宏是Excel自带的扩展功能,可以记录的内容包括对Excel格式和文字的修改,它会像录像机一样记录下你在Excel中的操作。当你有一系列的动作需要多次执行,并且每次执行动作的顺序又完全相同,就可以重新播放,把这些操作自动再执行一遍。所以对于办公中临时性的需求,使用宏要比掌握每个Excel操作对应的Python函数要更简单。
|
||||
|
||||
你可以使用宏的录制功能,把格式调整、复制粘贴、打印等重复操作记录下来,并保存成一个**快捷键****。**当你需要重复执行这条流水线作业时,就可以通过执行快捷键实现自动化操作。
|
||||
|
||||
不过,虽然宏能够像录像机一样通过重放功能实现自动化,但是它默认情况下只能实现部分功能的录制,也就是半自动化,要想把另一部分也自动化,就要使用宏的底层实现VBA脚本,例如像批量打印这些需求,就需要VBA脚本的循环扩充宏来实现自动化。
|
||||
|
||||
所以我在这节课,还会带你学习宏的底层实现VBA脚本,利用VBA脚本可以扩展宏的功能,把手动操作部分实现自动化。
|
||||
|
||||
那么接下来,我就通过对Excel的任意一个工作表进行打印的案例,给你具体讲解一下宏的录制和执行。
|
||||
|
||||
### 如何实现Excel的批量打印
|
||||
|
||||
#### 使用宏,实现单个工作表的打印
|
||||
|
||||
为了方便你学习,我准备了一个包含6个工作表的Excel文件,这6个工作表命名分别为sheet1-sheet6。要想基于宏实现自动化打印,需要通过这个步骤来实现:
|
||||
|
||||
1. 录制宏;
|
||||
1. 手动执行一次操作;
|
||||
1. 停止宏录制;
|
||||
1. 通过快捷键执行宏。
|
||||
|
||||
首先我先来带你看一下,怎么把打印的过程录制为宏。
|
||||
|
||||
录制宏,需要指定**宏名称和快捷键**。你需要在Excel的“视图”菜单栏找到“宏”下拉列表,在其中选择“录制宏”按钮,点击按钮就会弹出“录制宏”窗口。此时你需要把宏名改为“打印工作表”,再把快捷键改为Ctrl+Shift+P,点击确认之后,你接下来对Excel的操作就会被宏自动记录了。
|
||||
|
||||
这里以录制“打印sheet2工作表”这个操作为例,我把录制宏的窗口截图贴在下方,供你参考。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a0/6e/a0718136496f0cc11f2fca2480d0386e.png" alt="">
|
||||
|
||||
录制前有两点需要你注意:
|
||||
|
||||
1. 快捷键如果和Excel默认的快捷键发生冲突, 那么默认的快捷键功能就会失效,因此在录制前,你在给宏指定快捷键的时候,应当避开默认快捷键。
|
||||
1. 另一点需要注意的是,点击确定后宏就开始录制了,因此任何需要重复操作之外的操作步骤,都有可能会影响执行宏时的结果,所以我们在录制过程中应尽量减少不必要的操作。
|
||||
|
||||
接下来,我需要手动执行一遍打印操作,并把操作过程录制为宏。具体操作步骤是:
|
||||
|
||||
1. 录制开始前先激活sheet2,以免把激活sheet2的步骤记录到打印过程。
|
||||
1. 在录制宏窗口点击“确定”按钮,开始录制。
|
||||
1. 选择文件-打印,为了让你能更好地观察到结果,我把打印机设置为打印到PDF,然后点击打印按钮。
|
||||
1. 设置pdf的路径,并手动填入文件名sheet2.pdf。
|
||||
1. 点击保存。
|
||||
|
||||
第三步是停止宏的录制。在点击Excel左下角方形按钮后,就可以停止录制。停止之后,一个新的宏就录制完成了。
|
||||
|
||||
停止录制的截图我放在下方,可以帮你快速找到这一功能在Excel中的位置。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/44/2c/447f3abyy709d2ed228252f7f6c2f52c.png" alt="">
|
||||
|
||||
最后一步是执行宏。例如我需要把Sheet4打印成PDF,可以先激活Sheet4,并执行快捷键Ctrl+Shift+P,进行打印。
|
||||
|
||||
通过使用宏进行单个工作表打印操作,你会发现宏的优点和缺点。
|
||||
|
||||
它的优点是记录操作步骤的方式简单,尤其适合对Excel进行多次重复的格式和内容调整。而且掌握宏还不用学习Excel之外的编程技能,就能实现重复任务的自动化。
|
||||
|
||||
不过它的缺点也很明显,在使用宏之前,我们激活工作表和执行宏之后指定保存文件的名称,都需要手动操作。这就和我们使用Python自动化处理Excel是类似的,我们把自动化处理工作分成三个部分:为重复任务准备变量、为重复任务编写了一个for循环程序反复执行,为执行之后的结果自动保存结果。
|
||||
|
||||
可以看到,宏实现的就是for循环中的流水线操作。而对于使用宏之前以及使用宏之后的操作,我们是可以通过VBA脚本来进行优化,从而把相关操作实现自动化。
|
||||
|
||||
所以今天这节课,我们就再来学习一下VBA脚本。Excel的宏是基于VBA脚本实现的,如果你需要将打印多个工作表的手工操作也使用宏自动实现,需要通过VBA脚本来扩展宏。
|
||||
|
||||
#### 使用VBA脚本的循环,打印多个工作表
|
||||
|
||||
接下来,我就教你怎样查看当前宏的VBA脚本,并通过新的VBA脚本来扩展当前的宏,从而实现工作表的自动化批量打印。
|
||||
|
||||
首先,我们需要查看当前宏的VBA脚本。我们可以使用**视图-宏-查看宏**按钮,选中要查看的宏,并点击右侧的编辑按钮,这样就可以在打开的VBA脚本编辑器窗口查看当前宏的VBA代码。
|
||||
|
||||
我把查看方法和代码都贴在下方,供你学习。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/6a/30/6a1e49d4f63ee5f425d8c0371bf9fe30.png" alt=""><img src="https://static001.geekbang.org/resource/image/d8/89/d8f0a9a3c8b73fa8b42fcc6c72348889.png" alt="">
|
||||
|
||||
这个VBA脚本就是宏实现打印单个文件的全部代码,它由三部分组成,分别是Sub过程、注释、实现打印的语句。
|
||||
|
||||
1. 过程,是VBA代码完成一个任务的所有操作的集合。例如在上面这段代码中,实现打印任务的所有操作都被放在“Sub 打印工作表()”这一过程中,当你按快捷键Ctrl+Shift+P之后,Excel会按照Sub过程中的代码来运行。而我们要想实现自动打印到文件,就需要在Sub过程中扩展宏记录的打印任务。
|
||||
1. 注释,是指用于向其他人描述“过程”实现的目的,注释的内容不会被VBA执行。它的格式是使用引号开头行,这一行都是注释的内容。这和Python中以#开头的行注释用法是相同的。
|
||||
1. 实现打印的语句。代码中这两行就是实现打印的语句,我把代码从截图中单独拿出来供你参考。
|
||||
|
||||
```
|
||||
ActiveWindow.SelectedSheets.PrintOut Copies:=1, _ Collate:=True, IgnorePrintAreas:=False
|
||||
|
||||
```
|
||||
|
||||
这段代码由三部分组成,这三部分分别是要操作的对象,对象的属性和方法,方法的参数。我们依次来看下:
|
||||
|
||||
第一部分,对象是指工作簿、工作表、单元格、图片、图表、透视表等Excel中的具体元素。在Sub**过程**中要对哪个元素做修改,就需要在过程中指定该**对象。**
|
||||
|
||||
**例如代码中的“ActiveWindow**代表了**活动的Excel窗口对象,它意味<strong><strong>着**</strong>宏将要对当前活动的窗口做一些动作。</strong>
|
||||
|
||||
第二部分对象的属性和方法,指的**是对象的一部分或一种行为。这里需要注意,属性和方法是有区别的。**
|
||||
|
||||
- 对象的属性用来描述对象的性质和特点。比如字体的颜色、字号等;
|
||||
- 对象的方法是指在对象上执行的某个动作,比如要移动、删除、打印这个对象。
|
||||
|
||||
例如下面这一行代码:
|
||||
|
||||
```
|
||||
ActiveWindow.SelectedSheets.PrintOut
|
||||
|
||||
```
|
||||
|
||||
在这一行代码中,**SelectedSheets是属性**,它代表当前活动窗口下被选定的工作表,**PrintOut是方法,<strong>它被ActiveWindow对象调用,表示将要执行打印这一行为。总结来说,这条语句的作用就是**打印当前活动的Excel窗口下选定的工作表。</strong>
|
||||
|
||||
第三部分是PrintOut方法的三个参数,它的三个参数更改了打印的默认行为。我把这三个参数写在下面供你参考:
|
||||
|
||||
```
|
||||
Copies:=1, Collate:=True, IgnorePrintAreas:=False
|
||||
|
||||
```
|
||||
|
||||
1. Copies参数指定打印份数为1份;
|
||||
1. Collate参数指定逐份打印;
|
||||
1. IgnorePrintAreas则忽略打印区域并打印整个对象。
|
||||
|
||||
宏就是按照上面这两行VBA代码实现打印的。不过在你对一个新的工作表执行宏的时候,会发现,你不仅需要手动选择要打印的工作表,还需要手动指定要保存的工作表的文件名称,所以我们可以扩展宏的默认功能,让VBA脚本从半自动化到自动化。
|
||||
|
||||
具体怎么做呢?在宏打印工作表的VBA语句的基础之上,我们只需要增加遍历工作表和自动指定输出文件名这两个功能,就可以实现工作表的自动化批量打印。
|
||||
|
||||
因此,我要在Sub过程中改造打印方法,增加这两项功能,增加之后的代码如下:
|
||||
|
||||
```
|
||||
Sub 打印工作表()
|
||||
'
|
||||
' 打印工作表 宏
|
||||
'
|
||||
' 快捷键: Ctrl+Shift+P
|
||||
|
||||
With Application.FileDialog(msoFileDialogFolderPicker)
|
||||
If .Show = -1 Then filepath = .SelectedItems(1) & "\"
|
||||
End With
|
||||
|
||||
For Each sht In ActiveWorkbook.Worksheets
|
||||
sht.Select
|
||||
ActiveWindow.SelectedSheets.PrintOut Copies:=1, _
|
||||
Collate:=True, IgnorePrintAreas:=False, _
|
||||
printtofile:=True, _
|
||||
prtofilename:=filepath & sht.Name & ".pdf"
|
||||
Next
|
||||
|
||||
End Sub
|
||||
|
||||
|
||||
```
|
||||
|
||||
通过快捷键“Ctrl+Shit+P”再次运行宏,你会发现改造之后的代码与改造前相比,有这样两个区别。
|
||||
|
||||
第一个区别是,改造前我们需要手动点击一个工作表,让它处于激活状态。而改造之后,宏会自动依次选择每个工作表。
|
||||
|
||||
第二个区别是,改造前每次执行宏的时候,需要手动输入要打印的pdf文件名。而改造后,宏会弹出**选择存放打印文件的目录**。当你选择了一个目录之后,宏会自动把所有的工作表,均以“工作表名称.PDF”作为文件名进行打印。
|
||||
|
||||
可以看到,改造之后的代码比默认的宏效率更高了。接下来我就来详细解释一下我是怎么使用VBA脚本遍历工作表,以及怎么自动输出文件名的。
|
||||
|
||||
在代码的第11行,“For Each ... In ”结构是VBA脚本的遍历功能,遍历的对象是“ActiveWorkbook.Worksheets”,这个对象表示当前激活的是工作簿中所有的工作表。那么我们把每个表存入sht后,就可以实现工作表的遍历操作了。
|
||||
|
||||
这里我还要再提醒你一下。VBA的遍历和Python的主要区别是,前者遍历需要使用Next语句结束,而Python是依靠缩进实现循环语句块结束的,这也是使用Python编写程序的同学经常会遗漏Next语句的地方。
|
||||
|
||||
再来看怎么实现自动打印PDF文件的功能。这一功能的实现由**弹出保存文件夹的对话框**和**整合文件路径**两部分组成。
|
||||
|
||||
第一部分是在代码的第7、8行,我使用了FileDialog对象,这个对象会弹出对话框让用户选择路径。同时,filepath 变量会得到用户选择的文件保存路径。
|
||||
|
||||
第二部分在代码的15、16行,我为PrintOut打印方法增加了两个参数。分别是:printtofile和prtofilename。
|
||||
|
||||
printtofile参数类似一个开关,使用这个参数的目的,是让打印函数由默认的弹出对话框让用户手动输入文件名改为“将对象打印到文件”。
|
||||
|
||||
另一个prtofilename参数指定了打印的对象将以什么文件名来保存打印结果。为了把保存的文件名设置为“路径+表名.pdf”的格式,我通过“&”符号连接了两个变量“filepath 、 sht.Name”和字符串 ".pdf"” ,这一就组成了“filepath & sht.Name & ".pdf"”的文件命名形式。
|
||||
|
||||
在这里我还想强调一下FileDialog的代码位置,我把FileDialog对象写在遍历之前,是因为我不希望每次读取工作表的时候,都需要选择一次存放路径,这样会让批量打印再次变成需要手动指定路径后才能执行,因此我就把**FileDialog对象的代码放在批量读取工作表之前**,这样也会提高VBA脚本的自动化程度**。
|
||||
|
||||
通过VBA脚本增强了默认录制宏的功能,实现了批量打印工作表的功能。
|
||||
|
||||
### 小结
|
||||
|
||||
在今天这节课,我教你使用了“宏”这个强大的功能。通过宏的录制与回放,你可以实现Excel的自动化操作。此外,当有些操作没法被宏自动记录的时候,你还可以通过手动编写VBA脚本,来扩展宏默认的功能,让对工作表或单元格的批量操作从半自动化到自动化。
|
||||
|
||||
我在这节课中用批量打印的例子,给你展示了VBA的通过对话框指定保存路径、遍历工作表增强默认宏的代码,为你展示了迭代、判断和变量赋值,以及VBA中最重要的对象和操作对象的属性和方法。
|
||||
|
||||
需要说明的是,VBA支持Office的所有对象,通过对象的属性和方法,再配合VBA语法的判断循环,就能弥补默认宏的不足,实现几乎所有Office办公的自动化操作。
|
||||
|
||||
不过VBA支持的对象多达上百个,我在这节课中只给你介绍了其中一个对象,也就是激活工作表这个对象。通过VBA脚本的语法配合激活工作表对象,你可以掌握VBA自动化的基本流程。如果你想了解VBA支持的所有对象及其属性方法,可以参考[官方文档](https://docs.microsoft.com/zh-cn/office/vba/api/overview/library-reference/reference-object-library-reference-for-office)获得更详细的介绍。当你用到哪个对象,从文档里搜索关键字,找到它即可。
|
||||
|
||||
### 思考题
|
||||
|
||||
按照惯例,最后我要给你留一道思考题。你能否通过InStr函数(判断包含在字符串中的某个关键字是否存在,存在返回关键字位置,不存在返回0 [参考](https://docs.microsoft.com/zh-cn/office/vba/language/reference/user-interface-help/instr-function))改造批量打印脚本,让脚本实现包含关键字“汇总”,然后再打印报表?
|
||||
|
||||
欢迎把你的思考和想法写在评论区,我们一起交流讨论。此外,你还可以点击课程详情页的“戳我进群”,扫描二维码,加入我们的课程读者群,我也会在群里为你解疑答惑。
|
||||
@@ -0,0 +1,230 @@
|
||||
<audio id="audio" title="15|PowerShell脚本:如何实现文件批量处理的自动化?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/41/21/4129fbd4dfded86ff981f8a247be4c21.mp3"></audio>
|
||||
|
||||
你好,我是尹会生。
|
||||
|
||||
在工作中,会遇到和Windows操作系统紧密结合又需要批量操作的工作需求,比如文件的批量重命名,还有按照扩展名搜索文件。那么今天这节课,我将给你介绍一个主要应用于Windows操作系统自动化的脚本--PowerShell。
|
||||
|
||||
你肯定会有疑问,为什么我们不用Python,而是要另外学习PowerShell脚本呢?原因就在于,遇到这类工作需求,PowerShell脚本会比Python功能更强大,使用更方便,学习起来也更容易。
|
||||
|
||||
首先,Windows的所有操作,都有对应的PowerShell操作,可以达到办公自动化的目标。而使用Python,会因为Windows没有提供接口,有些功能就不能完全实现,或者有些操作还需要手动执行。
|
||||
|
||||
其次,PowerShell的语法简洁,比Python更加友好,降低了你阅读代码的难度。这一点你在这节课我讲解的例子中会有更深刻的体会。
|
||||
|
||||
最后,PowerShell在Windows上能做到开箱即用,安装完成后就可以正常运行了。而Python还需要安装解释器和配置环境。比如在金融和证券领域中,基于公司的规定,你可能无法安装操作系统之外的软件,这时候PowerShell的优势就体现出来了。
|
||||
|
||||
## 什么是PowerShell?
|
||||
|
||||
PowerShell是**开源的终端命令解释器**,之所以被称作解释器,是因为它会把用户输入的命令翻译给操作系统去执行,也能把操作系统执行的结果返回给用户。
|
||||
|
||||
作为PowerShell的初学者,你刚开始理解起来会有点难度,不过别担心,我举个例子你就明白了。
|
||||
|
||||
比如,在商场中的娃娃机,你需要通过对摇杆的控制来移动爪子的位置,抓取想要的礼物,因为你自己是没法直接移动爪子的。那么把你移动摇杆的操作翻译成爪子移动操作的功能,这就是解释器。
|
||||
|
||||
为了强化你对PowerShell的理解,我再把使用PowerShell前后的情况给你做个对比。
|
||||
|
||||
Windows操作系统在日常工作中,我们会采用图形界面(GUI)进行各类办公操作。在没有使用PowerShell的时候,如果我要想添加、删除、修改用户,就得点击各种按钮、选择下拉菜单、鼠标右键点击用户图标。
|
||||
|
||||
想象一下,如果我给100个新员工创建账户,创建一个账户需要5分钟,那仅仅在用户添加这一个操作上,我就需要花费500分钟,效率是不是很低?
|
||||
|
||||
但是利用PowerShell,就可以自动化完成**用户添加**这一重复性的操作了。
|
||||
|
||||
从Windows Server 2012版本(一听就是个很古老的操作系统版本)开始,所有的GUI操作就完全可以基于PowerShell实现了。这意味着,你能用GUI界面实现Windows操作系统中的所有功能。
|
||||
|
||||
你看,微软已经给了我们这么现成的自动化工具,所以我们可以放心大胆地把Windows操作系统上的重复操作,都交给PowerShell,提高工作效率。像这些和Windows操作系统紧密结合又需要批量操作的工作需求,都是PowerShell最适用的工作场景。
|
||||
|
||||
那么接下来,我就以Windows中最常用的文件管理为例,为你讲解一下PowerShell如何对文件进行批量处理。
|
||||
|
||||
## 怎样使用PowerShell实现文件批量处理?
|
||||
|
||||
在对文件的批量处理中,我们经常会遇到两类场景。
|
||||
|
||||
1. 文件夹下的文件按照某一规则批量重命名。比如,为了项目文件名称工整,需要批量给文件夹/文件按照某些规律进行重命名。
|
||||
1. 将符合多个条件的扩展名从大量文件中找出来。比如,为了找到outlook里附件中的所有的压缩包,你需要使用搜索功能,一次性查找包含.zip .rar .7z多个扩展名的文件。
|
||||
|
||||
接下来就以文件批量的重命名,来为你讲解一下用Powershell怎么实现。
|
||||
|
||||
### 一行代码,实现文件批量重命名
|
||||
|
||||
使用PowerShell脚本实现文件的批量重命名,我们只需要一行代码。不过在这一行代码中,需要你掌握的PowerShell的概念比较多。所以我会通过一个案例,帮助你在学习的同时也能迅速掌握、内化。
|
||||
|
||||
首先我通过一行代码创建了10个文本文件,创建的PowerShell脚本是:
|
||||
|
||||
```
|
||||
foreach($num in (1..10)) { New-Item $num".txt" -type file }
|
||||
|
||||
```
|
||||
|
||||
通过这行脚本,我在当前目录下创建了名字为“1.txt-10.txt”这样10个文件。由于批量改名操作也会用到类似的语法,所以我先给你详细讲解一下**批量创建文件的脚本**。这个脚本包含了**循环、变量和命令三个部分**。
|
||||
|
||||
第一个部分,是我在脚本中使用的**foreach的循环功能。**
|
||||
|
||||
循环的运行次数由in关键字后面的次数确定,这里我为了创建10个文本文件,就使用了“1..10”的形式来产生1到10这十个数字,这样的话,foreach就会执行10次,而每一次循环num变量都会得到一个新的数字,并在foreach循环体“{ }”中被New-Item项执行一次。
|
||||
|
||||
第二个需要你掌握的部分叫做**自定义变量。**
|
||||
|
||||
在PowerShell中,变量名都是以”$”开头的,剩余字符可以是字母、数字和下划线等任意字符。并且PowerShell的变量名是不区分大小写的,比如“$num”和“$NUM”都表示相同的变量。我在代码中使用了“$num”自定义变量来记录每次循环的数字。
|
||||
|
||||
第三个需要掌握的部分叫做**命令**。
|
||||
|
||||
PowerShell的命令有三种类型,例如New-Item叫做Cmdlet类型, foreach()叫做工作流类型,还有PowerShell内置的函数和自定义函数类型。这三种命令类型有一个共同的特点,就是都**能被PowerShell执行**。那么为了讲解方便,我在这节课中把这三种命令类型统称为“**命令**”。
|
||||
|
||||
在代码中,“New-Item”命令用来创建新的文本文件。我在创建时使用了两个参数,第一个参数**“$num".txt"”用来指定文件名**,文件名为num变量和字符串“.txt”连接后的名字。第二个参数**“-type”用来指定创建的类型是文件**(而非文件夹)。
|
||||
|
||||
**PowerShell的脚本编写完成之后,接下来我们就需要运行它。**
|
||||
|
||||
它的执行方式非常简单。在Windows中使用快捷键“win+R”可以弹出运行界面,在运行界面输入**“powershell”**之后再按回车,便会弹出PowerShell的交互界面,此时我们只需要把代码输入到交互界面就行了。
|
||||
|
||||
如果你希望脚本内容能多次运行,你就可以把脚本保存为以**“ps1”作为扩展名的文件中。**例如,我可以把创建10个文件的脚本保存到“newtxt.ps1”文件中,反复执行时,可以进入PowerShell交互界面,并输入“.\路径\newtxt.ps1”来运行它。
|
||||
|
||||
我把执行的命令和结果截图,贴在下方供你参考。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/09/a4/09dfd35d74489e5cc623324b051de5a4.png" alt="">
|
||||
|
||||
创建了10个文本文件后,我想把它们统一进行改名,新的名字是“new_数字_new.txt”,即在这10个文件的文件名前后,都增加“new”字符串,改名之后的格式如下图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/70/17/70918364f5e2080e35e054856e52d117.png" alt="">
|
||||
|
||||
我把批量改名的代码从截图中单独拿出来,来重点讲解一下其中的**dir命令、管道符和Rename-Item命令及其参数,因为PowerShell就是通过管道符将多个命令组合在一起,实现批量改名的。**
|
||||
|
||||
```
|
||||
dir *.txt | foreach { Rename-Item $_ -NewName ("new_"+$_.BaseName+"_new.txt") }
|
||||
|
||||
|
||||
```
|
||||
|
||||
我来带你按照代码的执行顺序,从左到右,依次讲解这行代码的主要实现逻辑。
|
||||
|
||||
首先,这行代码最左侧的**dir命令**,它的功能是**在终端输出当前目录下所有文件和目录的名称。**
|
||||
|
||||
如果你要操作的文件没有在当前目录,可以使用“cd 要访问的目录”方式进入该目录下,再使用“dir”命令查看。为了更改文本文件的名称,我需要先通过“dir *.txt”来获得当前目录下所有以“.txt”结尾的文件和目录。
|
||||
|
||||
接下来是这行代码中出现的**“|”,被称作管道符**。就像它的名字一样,用一条管道把两个程序连接在一起。它的作用主要有两个:
|
||||
|
||||
1. 连接两条命令,PowerShell会从左到右依次执行。如果左侧程序没有执行完成,右侧程序则会进入阻塞状态,等待左侧程序执行完成后再执行。
|
||||
1. 把左侧命令的执行(输出)结果,通过管道,作为右侧程序的输入。在这行代码中,“dir”命令的输出,会通过管道符成为“Rename-Item”命令的输入,再通过foreach循环,实现对每个文本文件进行重命名的操作。
|
||||
|
||||
最后,我们来学习一下“Rename-Item”命令和它的参数。和“New-Item”一样,“Rename-Item”也是**PowerShell独有的Cmdlet类型命令**,它的功能是**实现文件的改名**。
|
||||
|
||||
PowerShell中一共有9个与“Item”相关的Cmdlet,你可以使用下面的命令获得所有的命令和它的帮助。
|
||||
|
||||
```
|
||||
PS> Get-Command -Noun Item
|
||||
|
||||
CommandType Name Definition
|
||||
----------- ---- ----------
|
||||
Cmdlet Clear-Item Clear-Item [-Path] <String[]...
|
||||
Cmdlet Copy-Item Copy-Item [-Path] <String[]>...
|
||||
Cmdlet Get-Item Get-Item [-Path] <String[]> ...
|
||||
Cmdlet Invoke-Item Invoke-Item [-Path] <String[...
|
||||
Cmdlet Move-Item Move-Item [-Path] <String[]>...
|
||||
Cmdlet New-Item New-Item [-Path] <String[]> ...
|
||||
Cmdlet Remove-Item Remove-Item [-Path] <String[...
|
||||
Cmdlet Rename-Item Rename-Item [-Path] <String>...
|
||||
Cmdlet Set-Item Set-Item [-Path] <String[]> ...
|
||||
|
||||
```
|
||||
|
||||
**“Item”<strong>被官方文档翻译为“项”,你可以和我一样,把它们理解为**要操作的对象</strong>,通过上面这些Cmdlet命令,就可以实现这些“项”的增删改查。当你需要改名,就可以用“Rename-Item” Cmdlet来实现。
|
||||
|
||||
我们了解了“Rename-Item”命令的功能后,再继续学习它的**参数格式和内容**。它的参数格式是: **“Rename-Item** 旧的文件名 **-NewName** 新的文件名**”**。我在代码中使用了这样一行命令对文件名称进行了修改:
|
||||
|
||||
```
|
||||
Rename-Item $_ -NewName ("new_"+$_.BaseName+"_new.txt")
|
||||
|
||||
```
|
||||
|
||||
在“Rename-Item”命令的参数中,你需要关注**“$_”这个内置变量**。它的功能是**表示当前对象。**在我们的例子中,它表示foreach每次循环时,通过“|”传入的文件名称。
|
||||
|
||||
不过当你需要改名时,还有另外一种方法,那就是使用“$**.BaseName”来获得文件(不包含扩展名的)基本名称,以及通过“$**.extension”来获得扩展名。例如:“10.txt”文件的基本名称是“10”,扩展名是“.txt”。当我把“10.txt”赋值给“$**”之后,就可以使用“$**.BaseName”取得基本名称“10”,使用“$_.extension”取得扩展名“.txt”。
|
||||
|
||||
在“Rename-Item”命令的参数“("new_"+$_.BaseName+"_new.txt")”,这部分代码中,除了提取了“10.txt”的基本名称“10”之外,我还利用“+”符号把"new"字符串和基本名称“10”连接,形成新的文件名“new_10_new.txt”字符串。也就是说,把将、新的字符串作为“Rename-Item”的参数,就实现了文件重命名。
|
||||
|
||||
在这里有一点需要你注意,“$_”从PowerShell3.0版本开始,就可以使用“$PSItem”
|
||||
|
||||
替代“$**”,虽然“$PSItem”在阅读上更加友好,但“$**”能够向后兼容,而且输入的内容更少。所以我会更推荐你使用“$_”。
|
||||
|
||||
通过对批量改名代码的例子与分析,你会发现虽然只有一行代码,但是其中包含了内置变量、循环、管道和重命名命令等功能的组合,PowerShell就是这样一种简洁而功能强大的脚本语言。
|
||||
|
||||
为了让你能对PowerShell更加得心应手,我再为你讲解一个利用同样逻辑,就可以实现的场景:从一个文件夹找到.zip和.rar扩展名的文件,带你来一起看一下怎么使用PowerShell一行命令,来按扩展名搜索文件。
|
||||
|
||||
### 按扩展名搜索文件怎么实现
|
||||
|
||||
当工作时间久了,你会发现自己的Outlook文件夹里有海量的附件,特别是压缩包占用空间非常大。如果我们逐一搜索,就会像大海捞针一样,找到自己想要的文件非常困难。那么此时,我们就可以按照扩展名通过一行脚本将它们全部找出来进行备份或整理到新的文件夹中。
|
||||
|
||||
要想实现按扩展名搜索文件,我们需要继续利用“dir”命令来取得当前目录下所有文件,以及利用“$_.extension”来取得文件的扩展名。
|
||||
|
||||
所以我首先使用如下命令,来获取当前目录下的扩展名都有哪些,便于接下来的搜索和查找。
|
||||
|
||||
```
|
||||
dir | foreach{$_.extension} | Get-Unique
|
||||
|
||||
执行结果
|
||||
.txt
|
||||
.zip
|
||||
.rar
|
||||
|
||||
```
|
||||
|
||||
这行代码会把当前目录下所有文件的扩展名显示出来,为了避免重复的扩展名会影响我后续的脚本编写,那么在这里,我使用了“Get-Unique”命令,把相同的扩展名去重,只保留一个。
|
||||
|
||||
代码的执行过程依然是从左向右依次执行。
|
||||
|
||||
- 首先,通过“dir”命令获取当前目录下所有的文件名称,把所有的文件名称作为“foreach”循环的输入,赋值给“$_”。
|
||||
- 然后再通过“$_.extension”取得每个文件的扩展名,之后进行输出,再次通过管道符,作为“Get-Unique”命令的输入。
|
||||
- 最后,“Get-Unique”会把所有扩展名作为输入处理,输出不重复的扩展名。
|
||||
|
||||
通过观察所有扩展名的脚本执行结果,确定要搜索的目录中,包含了我们需要的“.zip”和“.rar”之后,我们再取出符合扩展名的文件名称。为了实现这一功能,我们还需要使用一个新的命令:**“Where-Object”。**
|
||||
|
||||
**“Where-Object”<strong>也是Cmdlet类型的命令,它的用法是**对管道中的每个对象进行筛选,把不符合条件的对象删除</strong>。那怎么判断管道中的对象是否符合条件呢?依据就是“Where-Object”命令后面“{}”中的参数。
|
||||
|
||||
“{}”中可以使用命令、也可以使用比较运算符。如果“{}”中使用命令,且命令执行结果为True,则“Where-Object”会保留对象进行输出或传入后续的管道,如果命令结果为False,则删除对象。
|
||||
|
||||
此外,如果“{}”中使用了比较运算符,就根据比较运算符的结果对对象进行相应操作。同命令结果一样,如果为True,则保留对象;如果为False,则删除对象。
|
||||
|
||||
比较运算符一共有10个,它是以“-”开头,跟着运算符名称,运算符的名称是大于、等于、小于的首字母缩写,我把比较运算符整理成表格,供你参考:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c1/53/c17e2dc85b3ef061c47971b00f333e53.png" alt="">
|
||||
|
||||
为了便于你理解比较运算符,我通过一个例子,来给你讲解怎么搜索“.zip”扩展名的文件。
|
||||
|
||||
```
|
||||
dir | Where-Object{ $_.extension -eq ".zip" }
|
||||
|
||||
```
|
||||
|
||||
在这段代码中,我使用了“-eq”比较运算符,实现了文件扩展名是否和“.zip”字符串相等的判断。
|
||||
|
||||
脚本通过dir命令可以获得当前目录下所有的文件,再通过“Where-Object”命令,依次对管道中的对象进行判断。如果扩展名为“.zip”则比较的结果为True,“Where-Object”命令执行完成后,PowerShell会在终端显示该文件名称,否则就会删除该对象,不在终端进行显示。
|
||||
|
||||
如果你还需要对文件大小、文件名称相似性等其他方式比较,可以参考比较运算符表格进行实现。
|
||||
|
||||
我们实现了单个扩展名的搜索之后,再来让这一行脚本的功能继续增强,让它能搜索多个扩展名。
|
||||
|
||||
为了同时搜索到“.zip”和“.rar”文件,我们需要**引入逻辑运算符**。在“Where-Object”命令的参数中,使用逻辑运算符,然后根据它两侧的执行结果是否为True,实现对扩展名的组合判断。例如下面的脚本:
|
||||
|
||||
```
|
||||
dir | Where-Object{ ($_.extension -eq ".zip" ) -or ($_.extension -eq ".rar" ) }
|
||||
|
||||
```
|
||||
|
||||
这行代码,过滤了管道中文件的扩展名是否包含“.zip”或者包含“.rar”。我在代码中使用的“-or”逻辑运算符的含义是,它的两侧扩展名和“.zip”、“.rar”任意一个相等,返回结果就是True,“Where-Object”命令就会把文件名称打印到屏幕上,如果返回的结果为False,对象仍然会被删除掉。
|
||||
|
||||
标准逻辑运算符我也为你整理了一个表格,你可以参考。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/6b/d8/6b2a277403b4781fe696bd430de420d8.png" alt="">
|
||||
|
||||
总结来说,通过增加逻辑运算符,我们就能实现对多个扩展名的搜索功能。
|
||||
|
||||
## 小结
|
||||
|
||||
最后我来为你做个总结,我通过批量改名和按多个扩展名搜索文件这两个例子,为你展示了PowerShell脚本的命令和管道。
|
||||
|
||||
命令中的Cmdlet类型能够支持Windows中所有的对象,其中对文件操作最常用的四个Cmdlet类型命令是:New-Item、Rename-Item、Where-Object和Get-Unique。它们也是我在这节课中为你着重介绍的命令。在PowerShell中,你掌握的Cmdlet越多,能够实现的功能就越强大,因此,我把[官方文档](https://docs.microsoft.com/zh-cn/powershell/scripting/samples/manipulating-items-directly?view=powershell-7.1)地址提供给你,你可以通过扩展学习,掌握更多的Cmdlet命令。
|
||||
|
||||
此外,命令中的工作流类型可以实现循环,我在这节课给你介绍了foreach循环,通过foreach就可以实现批量操作,优化办公效率。
|
||||
|
||||
不过在你掌握了足够多的命令后,还需要掌握管道符。因为通过管道符能够连接命令,让命令可以按顺序执行,而通过对命令的组合,就可以实现多个命名的自动化运行,今儿实现Windows操作系统相关操作的自动化。
|
||||
|
||||
## 思考题
|
||||
|
||||
按照惯例,我来为你留一道思考题,你能否通过官方文档查找到删除项的命令,并实现“.txt”扩展名文件的批量删除?请你大胆尝试一下。
|
||||
Reference in New Issue
Block a user