我想获取放置在表格中的ActiveX按钮的位置(行和列)。 到目前为止,我只知道如何抓住按钮
Selection.Fields.Item(1).OLEFormat.Object
所有ActiveX控件都列在
中Me.Content.InlineShapes
我似乎可以通过
访问父表selection.tables.item(1)
但我不知道如何确定该表格中按钮的位置,例如c5r8
答案 0 :(得分:0)
我使用以下代码逐步测试我的理论。结果证明是正确的。
Private Sub TestAX()
Dim Rng As Range
With ActiveDocument.Tables(1).Range
' Debug.Print .Start, .End
' Debug.Print .InlineShapes.Count
' Debug.Print .InlineShapes(1).OLEFormat.Object.Name
Set Rng = .InlineShapes(1).Range
End With
With Rng
' Debug.Print .Start, .End
' Debug.Print .Cells.Count
Debug.Print .Cells(1).ColumnIndex, .Cells(1).RowIndex
End With
End Sub
我开始只使用过程中的第一个Debug.Print
。当它工作时,我禁用了该行并尝试了下一行,直到我得到了我想要的结果。下一步是创建一个循环,循环遍历表中的所有InlineShapes,使用循环,如今天早上所述。
答案 1 :(得分:0)
感谢您的投入,并原谅我迟到的回复。 在你的建议的帮助下,我能够编写一些代码的目的是:
代码变得相当复杂,因为删除已经存在的按钮的代码不能很好地工作。最终我得出的结论是由于Word中的错误。
重新编号行的代码主要是自我解释。我遇到了两个主要障碍:
我的证据是为了弄清楚,如果一行必须编号很简单。仅检查一行中的第一个单元格是否为数字,这意味着您必须在运行代码之前准备表格,否则它将无法工作。
为了使处理时间保持较低,仅当循环的当前单元格位于最后一列时才执行检查。从那以后我参考第一个细胞等
为了区分单元格是否包含文本表单字段,我通过属性...Range.FormFields.Count
对其进行了校对。这意味着每个单元格只使用纯文本或文本格式字段
只有当您选择要编辑的表时,代码才有效,否则我必须搜索整个文档才能找到合适的表格,但我还没有找到一种简单的方法。
Private Sub CB_ReNumberDocTable_Click()
Dim toRemoveArray() As Variant
Dim ceTableCell As Cell, ceFirstCellinRow As Cell
Dim tabThisTable As Table
Dim i As Integer, iCurrentCol As Integer, iCurrentRow As Integer, iNoCol As Integer
Dim stCellText As String
toRemoveArray = Array(Chr(13), Chr(7))
Set tabThisTable = Selection.Tables(1)
iNoCol = tabThisTable.Range.Columns.Count
i = 1
For Each ceTableCell In tabThisTable.Range.Cells '.Columns(iNoCol) -> not working since mixed celles
iCurrentCol = ceTableCell.Range.Cells.Item(1).ColumnIndex
iCurrentRow = ceTableCell.Range.Cells.Item(1).RowIndex
If iCurrentCol = iNoCol Then
Set ceFirstCellinRow = tabThisTable.Cell(iCurrentRow, 1)
stCellText = toRemoveFromString(ceFirstCellinRow.Range, toRemoveArray)
If IsNumeric(stCellText) Then
If ceFirstCellinRow.Range.FormFields.Count = 1 Then
ceFirstCellinRow.Range.FormFields.Item(1).Result = Format(i, "00")
Else
ceFirstCellinRow.Range.Text = Format(i, "00")
End If
i = i + 1
End If
End If
Next
Set tabThisTable = Nothing
Set ceFirstCellinRow = Nothing
End Sub
我的代码的后续部分变得相当复杂,因为它从未完全删除所有当前按钮。为了追溯,我想给任何按钮一个唯一的,自我解释的名称,而不是引用Word给出的随机名称。
每个按钮的名称shell都以行的索引号终止。这意味着每行只有一个按钮,因此您最好删除所有行中的所有按钮,除了具有独立唯一名称的某些按钮,例如,触发这个宏。
第一次运行它时删除运行得很好但是从第二次开始它跳过一个按钮但删除了其中一个不相关的按钮,虽然过滤器,什么决定要删除什么按钮以及什么不是非常简单明了
Private Sub CB_CreateSAPButtonsStep1_Click()
Dim isShape As InlineShape
Dim isShape1 As InlineShape
Dim isShape2 As InlineShape
Dim isShape3 As InlineShape
Dim tabThisTable As Table
Dim i As Integer
Dim stShapeName As String
Dim stSenderName As String
Set tabThisTable = Selection.Tables(1)
stSenderName = Selection.Fields.Item(1).OLEFormat.Object.Name
If tabThisTable.Range.InlineShapes.Count > 0 Then
For i = tabThisTable.Range.InlineShapes.Count To 1 Step -1
Set isShape = tabThisTable.Range.InlineShapes.Item(i)
Set isShape1 = tabThisTable.Range.InlineShapes.Item(1)
Set isShape2 = tabThisTable.Range.InlineShapes.Item(2)
Set isShape3 = tabThisTable.Range.InlineShapes.Item(3)
stShapeName = isShape.OLEFormat.Object.Name
If Not isShape.OLEFormat.Object.Name = isShape1.OLEFormat.Object.Name Then 'stShapeName = "CB_ReNumberDocTable" Then 'InStr(1, isShape.OLEFormat.Object.Name, stSAPButtonName, 1) > 0 Then
If Not isShape.OLEFormat.Object.Name = isShape2.OLEFormat.Object.Name Then 'stShapeName = "CB_CreateSAPButtonsStep1" Then
If Not isShape.OLEFormat.Object.Name = isShape3.OLEFormat.Object.Name Then 'stShapeName = "CB_CreateSAPButtonsStep2" Then
Debug.Print "delete :" & isShape.OLEFormat.Object.Name
tabThisTable.Range.InlineShapes.Item(i).Delete
End If
End If
End If
Next
End If
Set tabThisTable = Nothing
Set isShape = Nothing
End Sub
此代码证明行是否必须编号,作为重新编号代码并在行的最后一个单元格中插入一个按钮。
然后按钮被正确地重命名和格式化。由于之前解释的错误从第二次运行开始失败。所以我删除我必须手动删除剩余按钮再次运行它。幸运的是,我不经常这样做。
Private Sub CB_CreateSAPButtonsStep2_Click()
Dim toRemoveArray() As Variant
Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent, moModul As VBIDE.VBComponent
Dim tabThisTable As Table
Dim i As Integer, iCurrentCol As Integer, iCurrentRow As Integer, iNoCol As Integer
Dim stSAPButtonModuleName As String, stSAPButtonName As String, stCellText As String, stcode As String,
Dim isShape As InlineShape
Dim ceTableCell As Cell, ceFirstCellinRow As Cell
iNoCol = Selection.Tables(1).Range.Columns.Count
stSAPButtonModuleName = "mo_SAPLinkButtons"
stSAPButtonName = "CB_SAPLink"
toRemoveArray = Array(Chr(13), Chr(7))
Set tabThisTable = Selection.Tables(1)
Set VBProj = ActiveDocument.VBProject
Application.ScreenUpdating = False
For Each moModul In VBProj.VBComponents 'http://www.cpearson.com/excel/vbe.aspx
If moModul.Name = stSAPButtonModuleName Then
Set VBComp = VBProj.VBComponents(stSAPButtonModuleName)
VBProj.VBComponents.Remove VBComp
End If
Next
Set VBComp = VBProj.VBComponents.Add(vbext_ct_StdModule)
VBComp.Name = stSAPButtonModuleName
'Exit Sub
'Debug.Print Now
'https://social.msdn.microsoft.com/Forums/office/en-US/da87e63f-676b-4505-adeb-564257a56cfe/vba-to-clear-the-immediate-window?forum=exceldev
'Application.SendKeys "^g ^a {DEL}"
'Call ClearImmediateWindow
i = 1
For Each ceTableCell In tabThisTable.Range.Cells '.Columns(iNoCol) -> not working since mixed celles
iCurrentCol = ceTableCell.Range.Cells.Item(1).ColumnIndex
iCurrentRow = ceTableCell.Range.Cells.Item(1).RowIndex
If iCurrentCol = iNoCol Then
Set ceFirstCellinRow = tabThisTable.Cell(iCurrentRow, 1)
stCellText = toRemoveFromString(ceFirstCellinRow.Range, toRemoveArray)
If IsNumeric(stCellText) Then
'Debug.Print "create shape"
'http://ccm.net/faq/1105-adding-a-vba-commandbutton-with-its-respective-the-code
'https://support.microsoft.com/de-ch/help/246299/how-to-add-a-button-to-a-word-document-and-assign-its-click-event-at-run-time
Set isShape = ceTableCell.Range.InlineShapes.AddOLEControl(ClassType:="Forms.CommandButton.1") ', Left:=0, Top:=0, Width:=15.75, Height:=11.25)
isShape.OLEFormat.Object.Caption = ""
isShape.OLEFormat.Object.Height = 11.25
isShape.OLEFormat.Object.Width = 15.75
isShape.OLEFormat.Object.BackColor = RGB(255, 255, 255) '&HFFFFFF
isShape.OLEFormat.Object.ForeColor = RGB(255, 255, 255) '&HFFFFFF
isShape.OLEFormat.Object.BackStyle = fmBackStyleTransparent
'isShape.OLEFormat.Object.Name = stSAPButtonName & Format(iCurrentRow, "00")
stcode = "Private Sub " & isShape.OLEFormat.Object.Name & "_Click()" & vbCrLf & _
" call openSAPLink" & vbCrLf & _
"End Sub"
Set isShape = Nothing
VBProj.VBComponents(stSAPButtonModuleName).CodeModule.AddFromString stcode
i = i + 1
End If
End If
' Debug.Print ceTableCell.Range
' Debug.Print ceTableCell.Range.Cells.Item(1).ColumnIndex
' Debug.Print ceTableCell.Range.Cells.Item(1).RowIndex
Next
Application.ScreenUpdating = True
Set tabThisTable = Nothing
Set VBProj = Nothing
Set VBComp = Nothing
Set moModul = Nothing
Set isShape = Nothing
Set ceFirstCellinRow = Nothing
For i = 1 To iNoCol
'Debug.Print Selection.Tables(1).Range.Columns(iNoCol - 1)
Next
End Sub
这个小助手除去了Chr(13)& CHR(7)
Private Function toRemoveFromString(stString, toRemove())
Dim chrItem As Variant
For Each chrItem In toRemove()
stString = Replace(stString, chrItem, "")
Next
toRemoveFromString = stString
End Function
用于清除即时窗口的仍然有缺陷的代码
Private Sub ClearImmediateWindow()
'https://www.mrexcel.com/forum/excel-questions/300075-clear-visual-basic-applications-editor-immediate-window.html
'https://www.experts-exchange.com/questions/28426212/How-to-clear-the-Immediate-Window-in-VBA.html
'https://access-programmers.co.uk/forums/showthread.php?t=253466
On Error Resume Next
Dim winImm As VBIDE.Window
Dim winActive As VBIDE.Window
' set the Window object variable to the Current Window for later reactivation
Set winActive = VBE.ActiveWindow
' set the Window object variable to the Immediate Window
Set winImm = VBE.Windows("Immediate")
' now clear it as you would do "manually"
winImm.SetFocus
Application.VBE.Windows.Item("Immediate").SetFocus
SendKeys "^({Home})", True
SendKeys "^(+({End}))", True
SendKeys "{Del}", True
Debug.Print Now
Set winImm = Nothing
'set focus back on window that was active before
'winActive.SetFocus
End Sub