【Excel自动化办公Part3】:工作表的创建、删除、复制和修改名称,冻结窗格,添加筛选

本文详细介绍了如何在Excel中创建新工作表、删除已有的、复制工作表以及修改工作表名称。此外,还讲解了冻结窗格和添加筛选功能的基本用法。深入理解这些技巧,提升工作效率。

目录

一、工作表的创建、删除、复制和修改名称

1、创建新的工作表

2、删除工作表

3、复制工作表

4、修改工作表名称

 二、冻结窗格

三、添加筛选


一、工作表的创建、删除、复制和修改名称

1、创建新的工作表

workbook.create_sheet(sheet名称)

2、删除工作表

workbook.remove(sheet实例)

3、复制工作表

workbook.copy_worksheet(sheet实例)

4、修改工作表名称

sheet.title=新的名称



 二、冻结窗格

sheet.freeze_panes='D2'



三、添加筛选

sheet.auto_filter.ref=sheet.dimensions

&#39; 主过程:生成零件编码汇总表(修复日期显示问题) Public Sub GeneratePartsSummary() On Error GoTo ErrorHandler Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Application.EnableEvents = False &#39; === 工作表设置 === Dim srcSheet As Worksheet, destSheet As Worksheet Set srcSheet = ThisWorkbook.Sheets("订单汇总") Set destSheet = ThisWorkbook.Sheets("推移表") &#39; === 获取源数据范围 === Dim lastRow As Long, lastCol As Long lastRow = srcSheet.Cells(srcSheet.Rows.Count, 1).End(xlUp).Row lastCol = srcSheet.Cells(1, srcSheet.Columns.Count).End(xlToLeft).Column If lastRow < 2 Then MsgBox "源数据表中没有可处理的数据", vbExclamation Exit Sub End If &#39; === 读取源数据到数组 === Dim srcData As Variant srcData = srcSheet.Range(srcSheet.Cells(1, 1), srcSheet.Cells(lastRow, lastCol)).value &#39; === 创建字典存储汇总数据 === Dim dict As Object Set dict = CreateObject("Scripting.Dictionary") dict.CompareMode = vbTextCompare &#39; === 确定日期列范围 === Dim firstDateCol As Long: firstDateCol = 4 Dim dateColCount As Long: dateColCount = lastCol - firstDateCol + 1 &#39; === 遍历源数据 === Dim i As Long, j As Long, partCode As String Dim values() As Double ReDim values(1 To dateColCount) For i = 2 To lastRow partCode = Trim(CStr(srcData(i, 1))) If partCode = "" Then GoTo NextRow If Not dict.Exists(partCode) Then For j = 1 To dateColCount values(j) = 0 Next j dict.Add partCode, values Else values = dict(partCode) End If For j = firstDateCol To lastCol Dim colIndex As Long: colIndex = j - firstDateCol + 1 If IsNumeric(srcData(i, j)) Then values(colIndex) = values(colIndex) + CDbl(srcData(i, j)) ElseIf srcData(i, j) <> "" Then values(colIndex) = values(colIndex) + HandleNonNumericValue(srcData(i, j)) End If Next j dict(partCode) = values NextRow: Next i &#39; === 准备目标数据 === Dim destData() As Variant ReDim destData(1 To dict.Count + 1, 1 To dateColCount + 2) &#39; 写入标题行(保留原始日期格式) destData(1, 1) = "零件编码" destData(1, 2) = "状态" For j = 1 To dateColCount &#39; 直接复制源表的日期值(保持原始格式) destData(1, j + 2) = srcData(1, j + firstDateCol - 1) Next j &#39; === 写入数据 === Dim keys As Variant, rowIndex As Long keys = dict.keys rowIndex = 2 For i = 0 To dict.Count - 1 destData(rowIndex, 1) = keys(i) destData(rowIndex, 2) = "订单" values = dict(keys(i)) For j = 1 To dateColCount destData(rowIndex, j + 2) = values(j) Next j rowIndex = rowIndex + 1 Next i &#39; === 写入目标表 === destSheet.Cells.Clear Dim outputRange As Range Set outputRange = destSheet.Range("A1").Resize(UBound(destData, 1), UBound(destData, 2)) outputRange.value = destData &#39; === 日期格式修复 === FixDateFormat destSheet, srcSheet, firstDateCol, lastCol &#39; === 格式设置 === FormatSummarySheet destSheet ExitProcedure: Application.ScreenUpdating = True Application.Calculation = xlCalculationAutomatic Application.EnableEvents = True Exit Sub ErrorHandler: MsgBox "错误 " & Err.Number & ": " & Err.Description & vbCrLf & _ "发生在 " & Erl, vbCritical Resume ExitProcedure End Sub &#39; === 日期格式修复函数 === Private Sub FixDateFormat(destSheet As Worksheet, srcSheet As Worksheet, firstDateCol As Long, lastCol As Long) &#39; 获取源表日期列的格式 Dim srcDateFormat As String On Error Resume Next srcDateFormat = srcSheet.Cells(1, firstDateCol).NumberFormat If Err.Number <> 0 Then srcDateFormat = "yyyy-mm-dd" On Error GoTo 0 &#39; 计算目标表日期列范围 Dim destFirstDateCol As Long: destFirstDateCol = 3 &#39; 目标表日期从C列开始 Dim dateColCount As Long: dateColCount = lastCol - firstDateCol + 1 &#39; 应用源表日期格式到目标表 With destSheet.Range(destSheet.Cells(1, destFirstDateCol), _ destSheet.Cells(1, destFirstDateCol + dateColCount - 1)) .NumberFormat = srcDateFormat &#39; 特殊处理:确保日期值正确显示 If InStr(srcDateFormat, "yy") > 0 Then .EntireColumn.AutoFit &#39; 自动调整列宽显示日期 End If End With &#39; 复制列宽设置(确保完全匹配源表) srcSheet.Range(srcSheet.Cells(1, firstDateCol), srcSheet.Cells(1, lastCol)).EntireColumn.Copy destSheet.Range(destSheet.Cells(1, destFirstDateCol), _ destSheet.Cells(1, destFirstDateCol + dateColCount - 1)).EntireColumn.PasteSpecial Paste:=xlPasteColumnWidths Application.CutCopyMode = False End Sub &#39; 辅助函数:处理非数值数据 Private Function HandleNonNumericValue(inputVal As Variant) As Double If IsNumeric(inputVal) Then HandleNonNumericValue = CDbl(inputVal) Else Select Case UCase(Trim(CStr(inputVal))) Case "N/A", "NA", "-", "" HandleNonNumericValue = 0 Case Else On Error Resume Next HandleNonNumericValue = Val(Replace(inputVal, ",", "")) If Err.Number <> 0 Then HandleNonNumericValue = 0 On Error GoTo 0 End Select End If End Function &#39; 格式设置子过程 Private Sub FormatSummarySheet(ws As Worksheet) On Error Resume Next With ws &#39; 设置状态列格式 .Columns(2).NumberFormat = "@" &#39; 设置数字格式(跳过日期标题行) Dim dataStartRow As Long: dataStartRow = 2 Dim dataStartCol As Long: dataStartCol = 3 Dim lastDataRow As Long: lastDataRow = .Cells(.Rows.Count, 1).End(xlUp).Row Dim lastDataCol As Long: lastDataCol = .Cells(1, .Columns.Count).End(xlToLeft).Column If lastDataRow > 1 And lastDataCol >= dataStartCol Then .Range(.Cells(dataStartRow, dataStartCol), .Cells(lastDataRow, lastDataCol)).NumberFormat = "#,##0" End If &#39; 添加表头格式 With .Rows(1) .Font.Bold = True .Interior.Color = RGB(200, 200, 255) .HorizontalAlignment = xlCenter End With &#39; 安全冻结窗格 SafeFreezeHeader ws End With End Sub &#39; 安全冻结窗格子过程 Private Sub SafeFreezeHeader(ws As Worksheet) On Error Resume Next If ws.Visible = xlSheetVisible And Not ws.ProtectContents Then Dim prevSheet As Worksheet Set prevSheet = ActiveSheet ws.Activate With ActiveWindow .FreezePanes = False .SplitRow = 1 .FreezePanes = True End With prevSheet.Activate End If End Sub 该段代码已经能够实现数据筛选导出的功能,但是列标题中的日期值需要修改。列标题中的日期值修改为:利用交互窗口键入一个日期值,列标题中的日期值是从该日开始,往后顺延15天(包含该日),同时需要考虑日期在顺延过程中应该与实际日历相对应。请尽量保留上述代码的结构,重新生成一份完整的代码
07-11
Public Sub GenerateStockProjection() On Error GoTo ErrorHandler Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Application.EnableEvents = False &#39; 定义工作表对象 Dim srcSheet As Worksheet, destSheet As Worksheet Set srcSheet = ThisWorkbook.Sheets("推移表") &#39; 创建结果工作表 On Error Resume Next Application.DisplayAlerts = False ThisWorkbook.Sheets("结果").Delete Application.DisplayAlerts = True On Error GoTo 0 Set destSheet = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)) destSheet.Name = "结果" &#39; 获取库存数据块信息 Dim stockHeaderRow As Long, lastRow As Long, lastCol As Long lastRow = srcSheet.Cells(srcSheet.Rows.Count, 1).End(xlUp).Row stockHeaderRow = FindStockHeaderRow(srcSheet, lastRow) If stockHeaderRow = 0 Then MsgBox "未找到库存数据块", vbExclamation Exit Sub End If &#39; 获取日期范围 lastCol = srcSheet.Cells(stockHeaderRow, srcSheet.Columns.Count).End(xlToLeft).Column Dim startDate As Date startDate = srcSheet.Cells(stockHeaderRow, 3).value &#39; 准备结果表头 destSheet.Cells(1, 1).value = "零件编码" Dim col As Long For col = 1 To 15 destSheet.Cells(1, col + 1).value = startDate + (col - 1) destSheet.Cells(1, col + 1).NumberFormat = "m/d" Next col &#39; 创建字典存储数据 Dim dictStock As Object, dictOrder As Object, dictDemand As Object Set dictStock = CreateObject("Scripting.Dictionary") Set dictOrder = CreateObject("Scripting.Dictionary") Set dictDemand = CreateObject("Scripting.Dictionary") &#39; 使用数组快速读取数据 ReadDataToDictionaries srcSheet, dictStock, dictOrder, dictDemand, stockHeaderRow, lastRow &#39; 处理并输出结果(只对计算过的行进行负值判断前置) ProcessAndOutputData destSheet, dictStock, dictOrder, dictDemand, startDate &#39; 格式化结果表 FormatResultSheet destSheet ExitProcedure: Application.ScreenUpdating = True Application.Calculation = xlCalculationAutomatic Application.EnableEvents = True Exit Sub ErrorHandler: MsgBox "错误 " & Err.Number & ": " & Err.Description, vbCritical Resume ExitProcedure End Sub &#39; 查找库存标题行 Private Function FindStockHeaderRow(ws As Worksheet, lastRow As Long) As Long Dim r As Long For r = 1 To lastRow If UCase(Trim(ws.Cells(r, 2).value)) = "库存" Then FindStockHeaderRow = r Exit Function End If Next r FindStockHeaderRow = 0 End Function &#39; 批量读取数据到字典 Private Sub ReadDataToDictionaries(ws As Worksheet, dictStock As Object, dictOrder As Object, dictDemand As Object, stockHeaderRow As Long, lastRow As Long) Dim r As Long, partCode As String, status As String Dim dataRange As Range Set dataRange = ws.Range("A2:C" & lastRow) &#39; 使用数组一次性读取数据 Dim dataArray As Variant dataArray = dataRange.value &#39; 处理所有数据行 Dim i As Long For i = 1 To UBound(dataArray, 1) partCode = Trim(CStr(dataArray(i, 1))) status = Trim(CStr(dataArray(i, 2))) If partCode <> "" And status <> "" Then &#39; 根据状态存储数据 Select Case UCase(status) Case "库存" dictStock(partCode) = CDbl(dataArray(i, 3)) Case "订单" If Not dictOrder.Exists(partCode) Then dictOrder.Add partCode, GetDailyValues(ws, stockHeaderRow, i + 1) End If Case "需求" If Not dictDemand.Exists(partCode) Then dictDemand.Add partCode, GetDailyValues(ws, stockHeaderRow, i + 1) End If End Select End If Next i End Sub &#39; 获取每日值数组 Private Function GetDailyValues(ws As Worksheet, headerRow As Long, dataRow As Long) As Double() Dim values(1 To 15) As Double Dim col As Long For col = 1 To 15 values(col) = ConvertToDouble(ws.Cells(dataRow, col + 2).value) Next col GetDailyValues = values End Function &#39; 处理并输出数据(修改:只对计算过的行进行负值判断前置) Private Sub ProcessAndOutputData(destSheet As Worksheet, dictStock As Object, dictOrder As Object, dictDemand As Object, startDate As Date) Dim partCodes() As Variant partCodes = dictStock.keys &#39; 使用集合存储不同类型的行 Dim calculatedNegativeRows As New Collection &#39; 计算后有负值的行 Dim calculatedPositiveRows As New Collection &#39; 计算后无负值的行 Dim uncalculatedRows As New Collection &#39; 未计算的行(缺少订单或需求) Dim stockValue As Double Dim orderVals() As Double, demandVals() As Double Dim rowData() As Variant Dim hasNegative As Boolean Dim hasCalculated As Boolean &#39; 处理每个零件 Dim partCode As Variant For Each partCode In partCodes ReDim rowData(1 To 16) rowData(1) = partCode hasNegative = False hasCalculated = False &#39; 初始库存值 stockValue = dictStock(partCode) rowData(2) = stockValue &#39; 检查是否存在订单需求数据(只有两者都存在才计算) If dictOrder.Exists(partCode) And dictDemand.Exists(partCode) Then orderVals = dictOrder(partCode) demandVals = dictDemand(partCode) hasCalculated = True &#39; 计算后续库存 Dim colIndex As Long For colIndex = 3 To 16 stockValue = stockValue + orderVals(colIndex - 2) - demandVals(colIndex - 2) rowData(colIndex) = stockValue If stockValue < 0 Then hasNegative = True Next colIndex Else &#39; 缺少订单或需求数据,不计算后续库存 For colIndex = 3 To 16 rowData(colIndex) = "" &#39; 留空 Next colIndex End If &#39; 根据是否计算负值情况分类 If hasCalculated Then If hasNegative Then calculatedNegativeRows.Add rowData Else calculatedPositiveRows.Add rowData End If Else uncalculatedRows.Add rowData End If Next partCode &#39; 输出结果:先计算后有负值的行,再计算后无负值的行,最后未计算的行 Dim outputRow As Long: outputRow = 2 &#39; 输出计算后有负值的行 For Each rowItem In calculatedNegativeRows destSheet.Range("A" & outputRow).Resize(1, 16).value = rowItem outputRow = outputRow + 1 Next rowItem &#39; 输出计算后无负值的行 For Each rowItem In calculatedPositiveRows destSheet.Range("A" & outputRow).Resize(1, 16).value = rowItem outputRow = outputRow + 1 Next rowItem &#39; 输出未计算的行 For Each rowItem In uncalculatedRows destSheet.Range("A" & outputRow).Resize(1, 16).value = rowItem outputRow = outputRow + 1 Next rowItem &#39; 标记负值(只标记计算过的行) MarkNegativeValues destSheet, calculatedNegativeRows.Count, calculatedPositiveRows.Count, uncalculatedRows.Count End Sub &#39; 标记负值单元格(修改:只标记计算过的行) Private Sub MarkNegativeValues(ws As Worksheet, calcNegCount As Long, calcPosCount As Long, uncalcCount As Long) Dim r As Long, c As Long Dim startRow As Long, endRow As Long &#39; 只标记计算过的行(负值行正值行) startRow = 2 endRow = startRow + calcNegCount + calcPosCount - 1 For r = startRow To endRow &#39; 标记零件编码(如果属于负值行集合) If r <= startRow + calcNegCount - 1 Then ws.Cells(r, 1).Font.Color = RGB(255, 0, 0) End If &#39; 标记负值单元格 For c = 2 To 16 If IsNumeric(ws.Cells(r, c).value) Then If ws.Cells(r, c).value < 0 Then ws.Cells(r, c).Font.Color = RGB(255, 0, 0) End If End If Next c Next r End Sub &#39; 格式化结果表 Private Sub FormatResultSheet(ws As Worksheet) &#39; 设置标题格式 With ws.Rows(1) .Font.Bold = True .Interior.Color = RGB(200, 200, 255) .HorizontalAlignment = xlCenter End With &#39; 设置数字格式 With ws.Range("B2:Q" & ws.Rows.Count) .NumberFormat = "#,##0" .HorizontalAlignment = xlRight End With &#39; 自动调整列宽 ws.Columns("A:Q").AutoFit &#39; 冻结窗格 ws.Range("B2").Select ActiveWindow.FreezePanes = True &#39; 添加说明行 Dim lastRow As Long lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row ws.Cells(lastRow + 1, 1).value = "说明:" ws.Cells(lastRow + 1, 2).value = "红色部分表示具有完整数据并计算后出现负值的零件" End Sub &#39; 数值转换函数 Private Function ConvertToDouble(inputVal As Variant) As Double If IsNumeric(inputVal) Then ConvertToDouble = CDbl(inputVal) Else Select Case UCase(Trim(CStr(inputVal))) Case "N/A", "NA", "-", "", "NULL" ConvertToDouble = 0 Case Else ConvertToDouble = Val(Replace(inputVal, ",", "")) End Select End If End Function在这份代码的运行结果中,输出表”结果“中列标题的日期无法与源表推移表对应,要求生成的”结果“表应该与源表中的日期一致,请根据要求修改代码并生成一份完整的代码
最新发布
07-15
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

街 三 仔

你的鼓励是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值