VBA 操作PowerQuery表格和带名字的表格

目录

  • [零. 使用场景](#零. 使用场景)
  • [一. 刷新PowerQuery表格](#一. 刷新PowerQuery表格)
    • [1.1 方式一](#1.1 方式一)
    • [1.2 方式二](#1.2 方式二)
    • [1.3 方式三](#1.3 方式三)
  • [二. 向带名字的表格中插入数据](#二. 向带名字的表格中插入数据)
  • [三. 获取表格中的数据](#三. 获取表格中的数据)

零. 使用场景

⏹需要自动化动态的统计表格中的数据

  • 使用公式:不便于维护,表格中的数据是动态变化的
  • 使用VBA:不便于维护,为了统计要写很多代码
  • 使用PowerQuery:
    • 简单统计无需写代码
    • 复杂统计写的代码较少

👍使用VBA和PowerQuery结合的方式,能更好的进行自动化处理

  • Power Query 负责,获取数据 + 清洗
  • VBA 负责 调度 + 控制 + 自动化

一. 刷新PowerQuery表格

🔷当一个Excel中有若干个PowerQuery创建的表格时,每次一个个的手动刷新数据太麻烦。

使用VBA创建一个按钮,一键全部刷新。

1.1 方式一

  • 只需一行代码
  • 刷新当前打开的整个Excel,简单粗暴,最省事
  • 所有的数据连接,数据透视表都会被刷新
vbnet 复制代码
Sub MainSub()
	ThisWorkbook.RefreshAll
End Sub

1.2 方式二

  • 先获取到PowerQuery的所有连接对象,然后找到连接名
  • 然后通过连接名精确的根据连接对象进行刷新
vbnet 复制代码
Sub MainSub()
	Dim connectObj As WorkbookConnection
	' 获取当前Excel文件中的所有连接对象
	For Each connectObj In ThisWorkbook.Connections
	
	    ' 打印连接名字
	    Debug.Print connectObj.Name ' 查询 - 表1
	    ' 打印连接的类型
	    Debug.Print connectObj.Type
	
	    ' Power Query 一般名字是:查询 - xxx
	    If InStr(connectObj.Name, "查询") > 0 Then           
	        ' 刷新连接
	        connectObj.Refresh
	    End If
	Next
	' 根据连接名找到连接Powerquery的连接对象, 然后刷新
	ThisWorkbook.Connections("查询 - 表1").Refresh
End Sub

1.3 方式三

  • 先根据表格的名称找到表格对象
  • 然后使用表格对象进行刷新
vbnet 复制代码
Sub MainSub()
	Dim currentWs As Worksheet
    Dim tbl1 As ListObject

    ' 获取当前打开的Excel的指定的Sheet页
    Set currentWs = ThisWorkbook.Worksheets("Sheet2")
    ' 获取指定Sheet页中的指定表格
    Set tbl1 = currentWs.ListObjects("表1_2")

    ' 获取当前表格的类型
    ' 0 普通表格
    ' 1 外部数据
    ' 2 查询
    Debug.Print tbl1.SourceType
    
    ' 如果当前表格对象存在就刷新
    If Not tbl1.QueryTable Is Nothing Then
        tbl1.QueryTable.Refresh BackgroundQuery:=False
    End If
End Sub

二. 向带名字的表格中插入数据

🔷给表格命名之后,表格对变为超级表,使用VBA操作起来更加方便

vbnet 复制代码
' 强制要求变量必须要声明
' 如果变量不声明的话, 也能用, 但默认类型是Variant
' vba在使用的时候还需要默认转型
Option Explicit

Sub MainSub()

    ' 定义sheet对象和表对象
    Dim ws As Worksheet
    Dim tblObj As ListObject

    ' 获取指定的Sheet页对象
    Set ws = ThisWorkbook.Worksheets("Sheet3")
    ' 获取指定Sheet页中的指定表对象
    Set tblObj = ws.ListObjects("表3")

    ' 如果当前表格中有数据的话, 就直接清空
    If tblObj.ListRows.count > 0 Then
        tblObj.dataBodyRange.Delete
    End If

    ' 定义一个字典对象
    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")
    ' 向字典对象添加key和value
    dict("MPL_ERR001") = 10
    dict("MPL_ERR002") = 23
    dict("MPL_ERR003") = 26
    dict("QCH_ERR00A") = 52
    dict("QCH_ERR00B") = 45
    dict("QCH_ERR00C") = 28

    ' 遍历字典所用到的变量
    Dim key As Variant
    Dim arr() As String
    Dim row As ListRow
    Dim rowNum As Long

     ' 遍历字典
    For Each key In dict.Keys

        ' 表格新增加一行
        Set row = tblObj.ListRows.Add
        ' 获取当前的行号
        rowNum = tblObj.ListRows.count
        ' 通过下划线分隔字符串
        arr = Split(key, "_")

        ' 为新增的1行的每列都添加数据
        With row.Range
            ' 因为只有1行, 所以 → .Cells(1, 列下标)
            ' 第1列 → No
            .Cells(1, 1) = rowNum
            ' 第2列 → 系统名
            .Cells(1, 2) = arr(0)
            ' 第3列 → 错误码
            .Cells(1, 3) = arr(1)
            ' 第4列 → 值
            .Cells(1, 4) = dict(key)
        End With
    Next

    ' 设置表格的排序属性
    With tblObj.Sort.SortFields
        ' 清除当前表格的排序
        .Clear
        ' === 添加新的排序规则 ===
        '   Key:=tblObj.ListColumns(1).Range → 根据第1列排序
        '   SortOn:=xlSortOnValues → 根据单元格值的值排序
        '   Order:=xlDescending → 倒序(从大到小)
        '   Order:=xlAscending → 正序(从小到大)
        .Add Key:=tblObj.ListColumns(1).Range, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
    End With
            
    With tblObj.Sort
        ' 表示表格有表头
        .Header = xlYes
        ' 应用排序
        .Apply
    End With

End Sub

三. 获取表格中的数据

🔷列数据获取方式

  • 根据列名获取
  • 根据列索引获取

🔷列数据遍历

  • 可以先遍历获取列中的每个单元格
    • 然后获取每个单元格中的数据
    • 如果表格很大的话,这种方式效率较低
  • 先把列中的数据全部取出,放到数组中
    • 然后遍历数组即可
    • 效率会高一些
vbnet 复制代码
Option Explicit

Sub MainSub()

    ' 定义sheet对象和表对象
    Dim ws As Worksheet
    Dim tblObj As ListObject

    ' 获取指定的Sheet页对象
    Set ws = ThisWorkbook.Worksheets("Sheet3")
    ' 获取指定Sheet页中的指定表对象
    Set tblObj = ws.ListObjects("表3")

    ' 如果当前表格中没有数据的话, 提示用户
    If tblObj.ListRows.count <= 0 Then
        MsgBox "表格中没有数据, 请确认..."
        Exit Sub
    End If

    ' 表格相关变量
    Dim systemNameCell As Range
    Dim systemNameRange As Range

    ' 🔷根据表格的列名获取当前列的数据(不会包含表头的数据)
    Set systemNameRange = tblObj.ListColumns("系统名").DataBodyRange
    If systemNameRange Is Nothing Then
        MsgBox "当前列, 没有数据..."
        Exit Sub
    End If

    ' 遍历表格中指定列的数据
    For Each systemNameCell In systemNameRange
        Debug.Print systemNameCell.Value
    Next
    Debug.Print "============================"

    ' 🔷根据表格的列索引来获取当前列的数据并遍历
    For Each systemNameCell In tblObj.ListColumns(2).DataBodyRange
        Debug.Print systemNameCell.Value
    Next
    Debug.Print "~~~~~~~~~~~~~~~~~~~~~~~~~~~"

    ' ==============================
    ' 👍推荐写法: 
    '   直接读取当前列的数组
    '   然后遍历, 效率会更高
    ' 
    ' 如果一个个遍历单元格的话
    ' 当数据多的时候, 会影响效率
    ' ==============================
    Set systemNameRange = tblObj.ListColumns(2).DataBodyRange
    If systemNameRange Is Nothing Then
        MsgBox "当前列, 没有数据..."
        Exit Sub
    End If
    
    ' 🔷获取包含当前列中的所有的数据的数组
    Dim i As Long
    Dim dataArr As Variant: dataArr = systemNameRange.Value

    For i = 1 To UBound(dataArr, 1)
        Debug.Print dataArr(i, 1)
    Next

End Sub
相关推荐
tangyal3 小时前
Linux 核心操作合集(网络配置、XShell远程连接、vim文本编辑与操作、权限管理 实操手册)
excel
softbangong21 小时前
815-批量Excel文件合并工具,批量excel文件、工作表合并软件
linux·windows·excel·文件合并·excel合并·数据整理
城数派21 小时前
2000-2024年1km精度人口分布栅格数据(全球/全国/分省/分市)
arcgis·信息可视化·数据分析·excel
城数派1 天前
1984-2024年中国10米分辨率城市土地利用栅格数据(商业、公服、居住等9类)
arcgis·信息可视化·数据分析·excel
城数派1 天前
2015-2024年我国1km分辨率逐日地表温度(LST)栅格数据
数据库·arcgis·信息可视化·数据分析·excel
城数派1 天前
中国全国土壤有机碳密度数据集(2010-2024年)
数据库·arcgis·信息可视化·数据分析·excel
Python大数据分析@1 天前
Pandas相比Excel的优势是哪些?
excel·pandas
fengyehongWorld1 天前
Excel 添加自定义选项卡
excel
斯特凡今天也很帅2 天前
Excel在保留下拉选项的基础上,通过输入四级目录数据,在一级目录、二级目录、三级目录、五级目录的显示
excel