网站首页 > 知识剖析 正文
- 数据源:
- 分析:1、需要把消费时间列中的字符形式的数据,拆分成日期和时间格式。2、根据拆分的时间格式,用条件语句匹配出就餐早中晚夜时段标签。3、由于数据量大,如果直接用表格公式处理,会卡顿,所以必须借助数组去处理。4、用多条件计数函数去统计,并写入汇总表。
- 效果
点击汇总
- 实现代码
Sub huiz() '汇总
Dim arr() As Variant
Dim newarr() As Variant
Dim lastrow As Long
Dim lastcol As Long
Dim Rows As Long
Dim cols As Long
Dim i As Long, j As Long, k As Long
Dim mealType As String
'日期数据处理,拆分
With ThisWorkbook.Sheets("数据源") ' 最好指定工作表,以防当前活动工作表不是预期的
.Columns("L:T").ClearContents
' 获取最后一行和最后一列
lastrow = .Cells(.Rows.Count, 1).End(xlUp).Row
lastcol = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Cells(1, lastcol + 1) = "日期"
.Cells(1, lastcol + 2) = "时间"
.Cells(1, lastcol + 3) = "时段"
' 将范围的值读取到数组中
arr = .Range(.Cells(2, 1), .Cells(lastrow, lastcol)).Value
' 获取原数组的行数和列数
Rows = UBound(arr, 1)
cols = UBound(arr, 2)
' 定义新的数组,大小比原数组多3列
ReDim newarr(1 To Rows, 1 To cols + 3)
' 将原数组的数据复制到新数组中,并在新数组的最后一列添加数据
For i = 1 To Rows
' 复制原数组的数据
For j = 1 To cols
newarr(i, j) = arr(i, j)
Next j
' 在新数组的最后一列添加数据
newarr(i, cols + 1) = VBA.DateValue(arr(i, 5)) ' 从第5列获取日期数据
newarr(i, cols + 2) = VBA.TimeValue(arr(i, 5))
'newarr(i, cols + 3) = application.WorksheetFunction.IfError()
If VBA.TimeValue(arr(i, 5)) < VBA.TimeSerial(5, 0, 0) Then
mealType = "夜宵"
ElseIf VBA.TimeValue(arr(i, 5)) < VBA.TimeSerial(9, 0, 0) Then
mealType = "早餐"
ElseIf VBA.TimeValue(arr(i, 5)) < VBA.TimeSerial(15, 0, 0) Then
mealType = "午餐"
ElseIf VBA.TimeValue(arr(i, 5)) < VBA.TimeSerial(22, 0, 0) Then
mealType = "晚餐"
Else
mealType = "夜宵"
End If
newarr(i, cols + 3) = mealType
'在 VBA 中,Time 函数并不是一个内建的全局函数,而是 Application.WorksheetFunction.Time 的一部分,它通常用于 Excel 工作表函数。但是,在 VBA 代码中,我们通常使用 TimeSerial 函数来创建时间值,因为 Time 函数并不直接适用于 VBA 编程。
Next i
' 写入增加的列中
.Range(.Cells(2, lastcol + 1), .Cells(lastrow, lastcol + 1)).Value = Application.Index(newarr, 0, cols + 1) 'Application.Index 函数中的 0 用于指定返回一个一维数组
.Range(.Cells(2, lastcol + 2), .Cells(lastrow, lastcol + 2)).Value = Application.Index(newarr, 0, cols + 2)
.Range(.Cells(2, lastcol + 3), .Cells(lastrow, lastcol + 3)).Value = Application.Index(newarr, 0, cols + 3)
End With
Call ct
ThisWorkbook.Sheets("汇总").Activate
'排序
Columns("A:A").Select
With ActiveSheet.Sort
With .SortFields
.Clear
.Add key:=Range("A2"), Order:=xlAscending
End With
.Header = xlGuess
.MatchCase = False
.SortMethod = xlPinYin
.Orientation = xlSortColumns
.SetRange rng:=Range("A1:E32")
.Apply
End With
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("汇总")
For k = 1 To ws.Range("a" & ws.Rows.Count).End(xlUp).Row - 1
ws.Range("B" & k + 1) = Application.WorksheetFunction.CountIfs(ThisWorkbook.Sheets("数据源").Columns("L:L"), ws.Range("a" & k + 1), ThisWorkbook.Sheets("数据源").Columns("N:N"), ws.Range("B1"))
ws.Range("C" & k + 1) = Application.WorksheetFunction.CountIfs(ThisWorkbook.Sheets("数据源").Columns("L:L"), ws.Range("a" & k + 1), ThisWorkbook.Sheets("数据源").Columns("N:N"), ws.Range("C1"))
ws.Range("D" & k + 1) = Application.WorksheetFunction.CountIfs(ThisWorkbook.Sheets("数据源").Columns("L:L"), ws.Range("a" & k + 1), ThisWorkbook.Sheets("数据源").Columns("N:N"), ws.Range("D1"))
ws.Range("E" & k + 1) = Application.WorksheetFunction.CountIfs(ThisWorkbook.Sheets("数据源").Columns("L:L"), ws.Range("a" & k + 1), ThisWorkbook.Sheets("数据源").Columns("N:N"), ws.Range("E1"))
Next
'按时间段统计不重复的用餐人数
Call cl '调用清除指定区域数据对象
Call qc '调用去重重复数据后得就餐人数统计
End Sub
Sub ct() '日期去重,
Dim arr()
Dim dic As Object
Dim i As Long
Set dic = CreateObject("Scripting.Dictionary") ' 创建 Dictionary 对象
ThisWorkbook.Sheets("数据源").Activate
With ThisWorkbook.Sheets("数据源") ' 最好指定工作表,以防当前活动工作表不是预期的
lastrow = Cells(.Rows.Count, 1).End(xlUp).Row
lastcol = Cells(1, .Columns.Count).End(xlToLeft).Column
arr = .Range("a2", .Cells(lastrow, lastcol)).Value '除表头外的数据区域
'创建字典
For i = LBound(arr) To UBound(arr)
dic(arr(i, lastcol - 2)) = 1 '主要是用key的值,赋值随便,此处取第3列数据,去重复值
Next
End With
With ThisWorkbook.Sheets("汇总")
'Range("k1", Cells(1, Range("k1").Column - 1 + dic.Count)) = dic.Keys '不重复值按列显示
'Sheets("Sheet2").ListBox1.List = dic.Keys '不重复值取值到列表框显示
'不重复值按行显示
Dim key As Variant
Dim rowCounter As Long
Dim rng As Range
'清空指定区域数据
Set rng = .Range("a2:E" & Cells(Rows.Count, 5).End(xlUp).Row)
rng.ClearContents
rowCounter = 2 ' 从第二行开始,写入去重后得日期数据
For Each key In dic.Keys
.Cells(rowCounter, 1).Value = key
rowCounter = rowCounter + 1
Next key
End With
End Sub
Sub qc() '数据去重后得人数统计
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim ws As Worksheet
Dim rngCopy As Range
Dim rngPaste As Range
Dim rng As Range
' 设置源工作表和目标工作表
Set wsSource = ThisWorkbook.Sheets("数据源")
Set wsDest = ThisWorkbook.Sheets("去重数据")
Set ws = ThisWorkbook.Sheets("汇总")
' 创建一个范围,它包含你想要复制的列
Set rngCopy = wsSource.Range("B:B,L:L,N:N")
' 激活目标工作表,并确定粘贴范围(从 A1 开始)
wsDest.Activate
wsDest.Cells.ClearContents
Set rngPaste = wsDest.Range("A1")
' 复制源范围并粘贴到目标范围
rngCopy.Copy Destination:=rngPaste
' 直接对 A 到 C 列进行去重操作
wsDest.Range("A1:C" & wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Row).RemoveDuplicates Columns:=Array(1, 2, 3), Header:=xlYes
For k = 1 To ws.Range("a" & ws.Rows.Count).End(xlUp).Row - 1
ws.Range("F" & k + 1) = Application.WorksheetFunction.CountIfs(wsDest.Columns("B:B"), ws.Range("a" & k + 1), wsDest.Columns("C:C"), ws.Range("B1"))
ws.Range("G" & k + 1) = Application.WorksheetFunction.CountIfs(wsDest.Columns("B:B"), ws.Range("a" & k + 1), wsDest.Columns("C:C"), ws.Range("C1"))
ws.Range("H" & k + 1) = Application.WorksheetFunction.CountIfs(wsDest.Columns("B:B"), ws.Range("a" & k + 1), wsDest.Columns("C:C"), ws.Range("D1"))
ws.Range("I" & k + 1) = Application.WorksheetFunction.CountIfs(wsDest.Columns("B:B"), ws.Range("a" & k + 1), wsDest.Columns("C:C"), ws.Range("E1"))
Next
ws.Activate
End Sub
Sub cl() '清空指定区域数据
Dim ws As Worksheet
'Dim rng As Range
Set ws = ThisWorkbook.Sheets("汇总")
'Set rng = ws.Range("F2:I" & Cells(Rows.Count, 9).End(xlUp).Row)'当区域没有数据时,会清除掉标题
'rng.ClearContents
'rng.Select
ws.Range("F2", Cells(Rows.Count, 9)).ClearContents
End Sub
备注:
- 字典设置
Dim dic As Object
Set dic = CreateObject("Scripting.Dictionary") ' 创建 Dictionary 对象
- 数据清空和拷贝
Set wsSource = ThisWorkbook.Sheets("数据源")
Set wsDest = ThisWorkbook.Sheets("目标表")
' 创建一个范围,它包含你想要复制的列
Set rngCopy = wsSource.Range("B:B,L:L,N:N")
' 激活目标工作表,并确定粘贴范围(从 A1 开始)
wsDest.Activate
wsDest.Cells.ClearContents
Set rngPaste = wsDest.Range("A1")
' 复制源范围并粘贴到目标范围
rngCopy.Copy Destination:=rngPaste
- 选取数据区域
With ThisWorkbook.Sheets("数据源") ' 最好指定工作表,以防当前活动工作表不是预期的
lastrow = Cells(.Rows.Count, 1).End(xlUp).Row
lastcol = Cells(1, .Columns.Count).End(xlToLeft).Column
arr = .Range("a2", .Cells(lastrow, lastcol)).Value '除表头外的数据区域
end With
- 函数的调用
Application.WorksheetFunction.CountIfs()
VBA.TimeValue(arr(i, 5)) < VBA.TimeSerial(22, 0, 0)
- 数组的赋值
' 将范围的值读取到数组中
arr = .Range(.Cells(2, 1), .Cells(lastrow, lastcol)).Value
' 获取原数组的行数和列数
Rows = UBound(arr, 1)
cols = UBound(arr, 2)
' 定义新的数组,大小比原数组多3列
ReDim newarr(1 To Rows, 1 To cols + 3)
' 将原数组的数据复制到新数组中,并在新数组的最后一列添加数据
For i = 1 To Rows
' 复制原数组的数据
For j = 1 To cols
newarr(i, j) = arr(i, j)
Next j
' 在新数组的最后一列添加数据
newarr(i, cols + 1) = VBA.DateValue(arr(i, 5)) ' 从第5列获取日期数据
newarr(i, cols + 2) = VBA.TimeValue(arr(i, 5))
Next
- 上一篇: 自定义通用数组排序函数
- 下一篇: 怎么求第K大的数,topK 问题(快排的应用)java
猜你喜欢
- 2025-01-20 Excel中的6个经典排序技巧都不掌握,还敢称Excel达人?
- 2025-01-20 查询函数Choose、Lookup、Hlookup、Vlookup应用技巧解读
- 2025-01-20 一起学《C程序设计》第六课——数组、字符串及实战练习
- 2025-01-20 一文解决CSP-J考纲所有排序算法
- 2025-01-20 Excel VBA 自定义函数/数组字段定位/数组字段排序
- 2025-01-20 java基础,arrays类,Java的八种排序,冒泡排序
- 2025-01-20 excel中什么是数组,数组的作用是什么,这篇文章就带你入门
- 2025-01-20 16.9 数组 - 数据排序技术
- 2025-01-20 怎么求第K大的数,topK 问题(快排的应用)java
- 2025-01-20 JS 判断两个数组是否相等,元素以及顺序相等,顺序不同但元素相等
- 04-29php开发者composer使用看这一篇就够了
- 04-29引用和变量声明在不同语言中的实作
- 04-29PHP 没你想的那么差
- 04-29Ubuntu linux 上的 Nginx 和 Php 安装
- 04-29CentOS下通过yum搭建lnmp(单版本PHP)
- 04-29为什么 PHP8 是个高性能版本
- 04-29PHP8函数包含文件-PHP8知识详解
- 04-29使用无参数函数进行命令执行
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)