假设我有两个工作簿(工作簿1和工作簿2),我需要从工作簿1复制一张工作表到工作簿2。
复制的工作表的名称,例如“Board”有(ActiveX Controls),它引用了分配有宏的子例程,
还有像(圆角矩形,八角形)和图片这样的形状,它们引用了单元格值或分配有宏的子例程,
复制的工作表还具有图表,其中引用了单元格范围。
复制表的问题是所有子程序和形状
公式仍然参考源工作簿(
workbook1
)。运行时错误“438”:对象不支持此属性或方法
在这一行
If shp.Formula <> "" Then
Option Explicit
Option Compare Text
Sub Copy_Sheet_to_another_Workbook() 'Assumes this code is found in Workbook1 (ThisWorkbook)
Dim srcWs As Worksheet
Dim dstWb As Workbook
Dim dstWs As Worksheet
Dim shp As Shape
Dim srcWbName As String
Dim dstWbName As String
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
.DisplayAlerts = False
End With
Set srcWs = ThisWorkbook.Sheets("Board") 'name of the sheet to be copy
Set dstWb = Workbooks.Open("C:\Users\xxx\Desktop\Workbook2.xlsb") 'destination Workbook
srcWs.Copy Before:=dstWb.Sheets(1)
Set dstWs = dstWb.Sheets(2)
srcWbName = ThisWorkbook.name
dstWbName = dstWb.name
'Update VBA references to macros/subroutines in shapes with macros assigned
For Each shp In dstWs.Shapes
If shp.OnAction <> "" Then
If InStr(1, shp.OnAction, srcWbName, vbTextCompare) > 0 Then
shp.OnAction = Replace(shp.OnAction, srcWbName, dstWbName)
End If
End If
Next shp
'Update shapes with cell references in the formula
For Each shp In dstWs.Shapes
If shp.Formula <> "" Then
If InStr(1, shp.Formula, srcWbName, vbTextCompare) > 0 Then
shp.Formula = Replace(shp.Formula, srcWbName & "!", dstWbName & "!")
End If
End If
Next shp
'Update chart references
For Each chartObj In dstWs.ChartObjects
With chartObj.Chart
Dim srs As Series
For Each srs In .SeriesCollection
If InStr(1, srs.Formula, srcWbName, vbTextCompare) > 0 Then
srs.Formula = Replace(srs.Formula, srcWbName & "!", dstWbName & "!")
End If
Next srs
End With
Next chartObj
dstWb.Activate
With Application
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
.EnableEvents = True
.DisplayAlerts = True
End With
End Sub
更新1 - 似乎我必须选择每个形状,然后检查其公式并相应地修改它,
因为并非每个形状都有公式,所以我必须使用错误处理。
这种方法的缺点是它不适用于分组形状。
'Update shape formulas by selecting each shape (for shapes with cell references)
For Each shp In dstWs.Shapes
On Error Resume Next 'Ignore errors for shapes without a formula
shp.Select
If Selection.Formula <> "" Then
If InStr(1, Selection.Formula, "[" & srcWbName & "]", vbTextCompare) > 0 Then
Selection.Formula = Replace(Selection.Formula, "[" & srcWbName & "]", "")
End If
End If
On Error GoTo 0 'Reset error handling
Next shp
这似乎有点令人困惑。 形状对象没有属性公式,您也可以向形状添加公式,它将被识别为形状。 但这些形状是特殊的物体,例如椭圆形 -> 椭圆形 假设您插入一个椭圆形(我将使用它作为可以有公式的所有可能形状的示例)并给它一个公式。它将作为形状被发现,但不会呈现公式属性。即使你寻找物体。 问题可能是,椭圆形是隐藏元素,只需在对象资源管理器中查看并显示隐藏元素即可。
我想你必须知道,你使用哪些特殊类型的形状来迭代它们
Sub JustToShow()
Dim ov As Oval
For Each ov In ActiveSheet.Ovals
Debug.Print ov.Formula
Next ov
End Sub
但我认为,这种使用形状和公式的方式无论如何都更加重要。它们可能非常不稳定。
请尝试下一个测试子程序。
Sub ModifyFormulaMemorizeRange()
Dim wsSource As Worksheet, wsDest As Worksheet, rngFormula As Range, rngFormula1 As Range, cel As Range
Set wsSource = ActiveSheet
Set rngFormula = wsSource.UsedRange.SpecialCells(xlCellTypeFormulas)
For Each cel In rngFormula.Cells
cel.Formula = VBA.Replace(cel.Formula, "=", "xyz#@") 'use a string not probable to be found between existing...
Next cel
Stop 'please, check the transformed formulas
'copy the sheet after the active one:
wsSource.Copy after:=wsSource
Stop 'please, see the newly copied sheet
Set wsDest = wsSource.Next
Set rngFormula1 = wsDest.Range(rngFormula.Address)
For Each cel In rngFormula.Cells
cel.Formula = VBA.Replace(cel.Formula, "xyz#@", "=")
Next cel
wsSource.Calculate
Stop 'see the original sheet restored formulas...
'Change back formulas in the copied cells
For Each cel In rngFormula1.Cells
cel.Formula = VBA.Replace(cel.Formula, "xyz#@", "=")
Next cel
wsDest.Calculate
Stop 'check the copied cells formulas...
End Sub
Sub MemorizeShapesTextFormula()
Dim sh As Shape, ws As Worksheet, k As Long
Set ws = ActiveSheet
ReDim arrShFormula(ws.Shapes.Count)
For Each sh In ws.Shapes
If CBool(sh.TextFrame2.HasText) Then
sh.Select
With Selection
If isLinkedCell(.Formula, .Text) Then
arrShFormula(k) = sh.Name & "|=" & .Formula: k = k + 1
End If
End With
End If
Next sh
If k > 0 Then ReDim Preserve arrShFormula(k - 1)
Debug.Print Join(arrShFormula, " ") 'just to see what has been memorized
End Sub
Function isLinkedCell(cellAddress As String, shText As String) As Boolean
On Error Resume Next
If Range(cellAddress).Value = shText Then isLinkedCell = True
On Error GoTo 0
End Function
1.b.如何使用上面加载的数组来更改复制形状的公式:
Sub AdaptShapesTextFormulas()
Dim wsSource As Worksheet, sh As Shape, i As Long
Set wsSource = ActiveSheet.Next 'mentain selected the sheet where the array has been loaded...
For i = 0 To UBound(arrShFormula)
wsSource.Shapes(Split(arrShFormula(i), "|")(0)).Select
Selection.Formula = Split(arrShFormula(i), "|")(1)
Next i
End Sub
已编辑:
要处理分组形状,请使用下一个测试子:
Sub testGroupMembersFormula()
Dim sh As Shape, i As Long
For Each sh In ActiveSheet.Shapes
If sh.Type = msoGroup Then
For i = 1 To sh.GroupItems.Count
Debug.Print sh.GroupItems(i).Name
sh.GroupItems(i).Select
Debug.Print Selection.Formula
Next i
End If
Next sh
End Sub