【发布时间】:2016-07-16 10:19:43
【问题描述】:
我有一个例行程序,在日历上填满下一周每一天的商品市场的所有重要事件。我在页面上布置了一个日历网格,并且在每一天的列中每天都有十个命名单元格,即 Monday1、Monday2 等等(现在每天最多只能达到 10 个,即Monday10)。顺便说一句,单元格宽 2 格,深 2 格。很多时候,一天有超过 10 个事件。我正在尝试测试命名范围以查看它是否存在,如果不存在,则复制最后一个命名范围单元格的格式并将该单元格命名为系列中的下一个名称。
我对上述问题只有两个问题,首先是如何测试以确定命名范围的名称已经存在。我目前正在遍历 ThisWorkbook.Names 的整个列表,其中包含数千个命名范围。由于在生成日历时此迭代可能会运行超过 100 次,因此速度非常慢(正如预期的那样)。是否有更好、更快的方法来检查名称是否已作为命名范围存在?
第二个问题是如何复制 4 个单元格的格式,合并单元格,因为地址总是仅作为左上角单元格出现,因此偏移范围无法正常工作。为了让这段代码至少为列中的下一个合并单元组提供正确的范围,我四处乱窜
Set cCell = Range("Thursday" & CStr(y))
'even tho cCell is a 4 cell merged cell, cCell.Address returns the address of top left cell
Set destRange = Range(cCell.Address & ":" & cCell.offset(2, 0).offset(0, 1).Address)
录制宏以向下拖动格式,显示此代码。
Range("G22:H23").Select
Selection.AutoFill Destination:=Range("G22:H25"), Type:=xlFillFormats
Range("G22:H25").Select
由于 Range("G22:H23") 与 cCell 相同,Range("G22:H25") 与 destRange 相同。以下代码应该可以工作,但不能。
Set cCell = Range("Thursday" & CStr(y))
Set destRange = Range(cCell.Address & ":" & cCell.offset(2, 0).offset(0, 1).Address)
cCell.AutoFill Destination:=destRange, Type:=xlFillFormats
Application.CutCopyMode = False
cCell.offset(1, 0).Name = rangeName
仅供参考,如果我选择 cCell 并使用 Selection.AutoFill 也不起作用。
对于如何在需要时将单元格格式一次复制一个单元格,有什么想法吗?
更新:
这现在适用于将格式从一个合并单元格复制到另一个相同大小的单元格。出于某种原因,将 destRange 设置为整个范围(宏记录器显示的复制单元格和 pastecell 整个范围)不起作用,但将 destRange 设置为需要格式化的单元格范围,然后将 cCell 和 destRange 合并,并进行命名新范围更容易。
rangeName = "Friday" & CStr(y + 1)
priorRangeName = "Friday" & CStr(y)
namedRangeExist = CheckForNamedRange(rangeName)
If namedRangeExist = False Then
Set cCell = Range(priorRangeName)
Set destRange = Range(cCell.offset(1, 0).Address & ":" & cCell.offset(2, 0).offset(0, 1).Address)
cCell.AutoFill Destination:=Union(cCell, destRange), Type:=xlFillFormats
Application.CutCopyMode = False
destRange.Name = rangeName
End If
更新 #2
在 For 循环中命名范围存在问题(下面的代码在 For 循环中运行)。第一次找不到新的范围名称时,将 cCell 设置为先前的范围名称并运行代码以复制合并的单元格格式并命名新范围工作正常。这是代码
rangeName = "Thursday" & CStr(y + 1)
priorRangeName = "Thursday" & CStr(y)
namedRangeExist = DoesNamedRangeExist(rangeName)
If namedRangeExist = False Then
Set cCell = Range(priorRangeName)
Debug.Print "cCell:" & cCell.Address
Set cCell = cCell.MergeArea
Debug.Print "Merged cCell:" & cCell.Address
Set destRange = Range(cCell.offset(1, 0).Address & ":" & cCell.offset(2, 0).offset(0, 1).Address)
Debug.Print "Dest:" & destRange.Address
Debug.Print "Unioned:" & Union(cCell, destRange).Address
cCell.AutoFill Destination:=Union(cCell, destRange), Type:=xlFillFormats
Application.CutCopyMode = False
destRange.name = rangename
End If
结果在以下范围内
cCell:$G$22
合并的 cCell:$G$22:$H$23
目标:$G$24:$H$25
工会:$G$22:$H$25
但是如果第二次需要创建多个新的命名范围,则此代码会生成一个范围区域,如下所示的输出所示
cCell:$G$24:$H$25
那么为什么第一次运行时cCell的地址只显示为左上角的单元格地址,而第二次通过cCell的地址显示为整个合并的单元格范围?因为它确实如此,所以下一个代码行会产生一个范围对象错误
Set cCell = cCell.MergeArea
删除该代码行并将第一个 Set cCell 修改为此;
Set cCell = Range(priorRangeName).MergeArea
产生相同的错误。我可以通过设置一个计数器来解决这个问题,如果有多个,则绕过该代码行,但这不是首选解决方案。
【问题讨论】:
-
@Tim Williams...你是我在 SO 上找到的最好的 vba 人。这篇文章对 Update@2 有什么想法吗?
标签: vba excel formatting