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
相关推荐
梅孔立10 小时前
Java 基于 POI 模板 Excel 导出工具类 双数据源 + 自动合并单元格 + 自适应行高 完整实战
java·开发语言·excel
开开心心就好1 天前
系统重装前必备的智能驱动备份工具
windows·计算机视觉·计算机外设·excel·模块测试·csdn开发云·威胁分析
向宇it2 天前
php高性能的导出excel读写扩展——xlswriter,比传统的Spreadsheet要快很多
php·excel·xlswriter
yanweijie03172 天前
对比VLOOKUP、XLOOKUP、INDEX+MATCH三大查找函数
excel
Codiggerworld2 天前
Vim的语法:删除、复制、粘贴,像说话一样自然
编辑器·vim·excel
Pentane.2 天前
【数据分析 | 农业项目】蔬菜类商品的自动定价与补货决策 | Tableau & Excel
数据挖掘·数据分析·excel·tableau
happy_baymax2 天前
Simulink 端口自动生成工具 (v2.1)(EXCEL+m语言)
服务器·matlab·excel·simulink
SunnyDays10112 天前
如何使用 C# 高效实现 Excel 与 CSV 的互相转换
c#·excel·csv
热爱生活的五柒2 天前
excel的使用教程
excel
城数派2 天前
2025年我国省市县三级的平均坡度数据(Excel\Shp格式)
arcgis·信息可视化·数据分析·excel