(编辑:为解决方案增加了2个限制)
我有一个表(明智的listobject),我需要复制某些行。出于效率原因,我正在使用SourceListRow.Range.Value2 = DestListRow.Range.Value2(一次复制整个范围)。复制的单元格范围之后的所有公式列都会自动完全自动扩展到新行并对复制的数据进行操作。我在Windows上使用Excel 2010。
然而,尽管我已经使用了这种代码,但是我现在只是在使用Range.Value / Range.Value2时偶然发现了一个奇怪的现象:如果为它分配一个空字符串,那么最后一个单元格value不是空字符串,但它将为Empty。即:数据不会被忠实地复制,并且副本可能与源不同,特别是如果连续的公式使用ISBLANK等。因此,在处理副本与源文件时,相同的公式会有不同的结果。
见下面的测试代码。打开一个新的空白Excel工作簿,转到VBA,添加一个新模块并添加以下代码:
Sub Test()
ActiveSheet.Range("a1").Formula = "="""""
ActiveSheet.Range("b1").Formula = "=isblank(a1)"
ActiveSheet.Range("c1").Value2 = TypeName(ActiveSheet.Range("a1").Value2)
ActiveSheet.Range("a2").Value2 = ActiveSheet.Range("a1").Value2
ActiveSheet.Range("b2").Formula = "=isblank(a2)"
ActiveSheet.Range("c2").Value2 = TypeName(ActiveSheet.Range("a2").Value2)
ActiveSheet.Range("a3").Value2 = ""
ActiveSheet.Range("b3").Formula = "=isblank(a3)"
ActiveSheet.Range("c3").Value2 = TypeName(ActiveSheet.Range("a3").Value2)
ActiveSheet.Range("a4").Formula = ActiveSheet.Range("a1").Formula
ActiveSheet.Range("b4").Formula = "=isblank(a4)"
ActiveSheet.Range("c4").Value2 = TypeName(ActiveSheet.Range("a4").Value2)
Call ActiveSheet.Range("a1").Copy
Call ActiveSheet.Range("a5").PasteSpecial(xlPasteValues)
ActiveSheet.Range("b5").Formula = "=isblank(a5)"
ActiveSheet.Range("c5").Value2 = TypeName(ActiveSheet.Range("a5").Value2)
End Sub
然后运行它并查看表单;
怎么办?
所有想法都赞赏!
答案 0 :(得分:0)
SpecialCells(xlCellTypeBlank)和AutoFilter以不同方式处理空字符串。您的源数据是否可过滤?如果是这样,您是否可以使用占位符值,然后在复制后将单元格更改为.Formula = "="""""
?
我拿了你的示例代码并生成了工作簿,然后在它上面添加了一行用于过滤器头。下面的代码会将所有空字符串更改为" ChangeMe&#34 ;;然后,您可以复制值并替换" ChangeMe"的所有实例。在目的地中使用" ="""""使用Range.Replace。
Sub Test2()
ActiveSheet.Range("A2:A6").SpecialCells(xlCellTypeBlanks).Interior.Color = 255 'Just to prove that xlCellTypeBlanks only selects actual blanks
ActiveSheet.Range("A1:A6").AutoFilter Field:=1, Criteria1:="=" 'Shows both actual blanks and ZLS/null strings
ActiveSheet.Range("A1:A6").SpecialCells(xlCellTypeBlanks).EntireRow.Hidden = True 'Be able to use SpecialCells(xlCellTypeVisible) to reference all ZLS
ActiveSheet.Range("A2:A6").SpecialCells(xlCellTypeVisible).Value2 = "ChangeMe"
'Now unfilter and unhide your data, copy using .Value2, then .Replace "ChangeMe" with "="""""
End Sub
我认为这可以完成你想要做的事情 - 让我知道这是否是解决问题的正确方向。
编辑:误解原始问题。旧答案下方不正确。
虽然效率不如原始代码,但使用.AutoFilter比循环遍历许多单元格要有效得多。此外,.AutoFilter将零长度字符串和空单元格视为相同。
这样的事情:
Sub CopyAndClearFakeBlanks()
Dim WSSource As Worksheet
Dim WSDest As Worksheet
Dim LRow As Long
Dim LPasteRow As Long
Set WSSource = Sheets("Source Data")
Set WSDest = Sheets("Paste Here")
LRow = WSSource.Range("A:A").Find(what:="*", searchdirection:=xlPrevious).Row 'Note that this will ignore blanks, so you may want to use a different method for finding your last row. Depends on how your users would need the data if there are trailing blanks.
On Error Resume Next
LPasteRow = 2 'Always need at least one row before the data for filtering properly; you can delete after if necessary
LPasteRow = WSDest.Range("A:A").Find(what:="*", searchdirection:=xlPrevious).Row + 1
WSDest.AutoFilterMode = False
On Error GoTo 0 'ofc use proper error handling in your actual code
WSDest.Range("A" & LPasteRow & ":A" & LPasteRow + LRow - 1).Value2 = WSSource.Range("A1:A" & LRow).Value2
WSDest.Range("A" & LPasteRow - 1 & ":A" & LPasteRow + LRow).AutoFilter field:=1, Criteria1:="=" 'Show blank or ZLS only
On Error Resume Next
WSDest.Range("A" & LPasteRow & ":A" & LPasteRow + LRow).SpecialCells(xlCellTypeVisible).Clear 'Turn them into true blanks
WSDest.ShowAllData
WSDest.AutoFilterMode = False
On Error GoTo 0
Set WSDest = Nothing
Set WSSource = Nothing
End Sub