VBA invalid qualifier with string.copy - vba

I'm writing a code that loops through the textboxes of a word document. These textboxes contain a picture and a caption. So far, I have written a code that gets the caption from the textbox (which I checked through MsgBox caption).
I want to copy the caption, clear the textbox of all content, and then paste the old caption back in (because I'm trying to replace the pictures with an updated one). However, I keep getting an error with caption.Copy and have no idea why. It says that caption is an "Invalid Qualifier." I did some digging around online but haven't solved my problem.
This was the most-related thing I found: Invalid Qualifier error in Visual Basic 6.0
Anyway, here's my code. Any help would be appreciated!
Sub ReplaceImages()
Dim str As String
Dim captionTag As String
Dim imageTag As String
'Dim objShape As Variant Type Mismatch?
Dim fileName As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
'Select directory to match .PNG to figure in document
Set SelectFolder = Application.FileDialog(msoFileDialogFolderPicker)
With SelectFolder
.Title = "Select Directory"
.AllowMultiSelect = False
If .Show <> -1 Then GoTo ResetSettings
sPath = .SelectedItems(1) & "\"
End With
sFile = Dir(sPath & "*png")
Do While sFile <> ""
fileName = sFile
MsgBox fileName
imageTag = BetweenParentheses(fileName)
For Each objShape In ActiveDocument.Shapes
If objShape.Type = msoTextBox Then
Set shapePicture = objShape
str = objShape.TextFrame.TextRange.Text
If InStr(str, "(") > 0 Then
captionTag = BetweenParentheses(objShape.TextFrame.TextRange)
If captionTag = imageTag Then
If InStr(str, "Figure") > 0 Then
Dim firstTerm As String
Dim secondTerm As String
Dim caption As String
firstTerm = "F"
secondTerm = ")"
Dim startPos As Long
Dim stopPos As Long
Dim nextPosition As Long
nextPosition = 1
caption = objShape.TextFrame.TextRange.Text
Do Until nextPosition = 0
startPos = InStr(nextPosition, caption, firstTerm, vbTextCompare) - 1
stopPos = InStr(startPos, caption, secondTerm, vbTextCompare) + 1
caption = Mid$(caption, startPos + Len(firstTerm), stopPos - startPos - Len(firstTerm))
nextPosition = InStr(stopPos, caption, firstTerm, vbTextCompare)
Loop
caption.Copy 'This is where the error is
End If
End If
End If
End If
Next objShape
sFile = Dir
Loop
ResetSettings:
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False

The caption variable is a string while the Copy method only applies to objects in the Word object model.
You store the text from the TextFrame into the caption variable:
caption = objShape.TextFrame.TextRange.Text
And then manipulate it inside your loop.
If you want to keep the value of the caption variable, then assign the value to another variable:
Dim someOtherVariable As String
someOtherVariable = caption

There might be some different between Excel and Word VBA in embedded shapes, but the following should be easy enough to adopt to word:
Sub test()
Dim shp As Shape, s As String
Set shp = ActiveSheet.Shapes(1)
s = shp.TextFrame2.TextRange.Text ' this is a string which doesn't have a Copy method
Debug.Print s
'but:
shp.TextFrame2.TextRange.Copy 'copies to clipboard!
End Sub
You can double check that the text is in the clipboard by pasting it directly into the immediate window (or wherever).

Related

Powerpoint VBA actively select slide range based on string in textbox

I want to scan thorough a slide deck for text boxes containing a search string and leave the active presentation with Active selected slides.
*** I can search ok...>> Creating a list of slides with my text on
Function FindSlidesWithText(ByVal Owner As String) As String
Dim oSl As Slide
Dim oShp As Shape
Dim strSearch As String
Dim i As Integer
Dim slideList As String
If Owner = "" Then
strSearch = InputBox("Enter the text to search for:")
Else
strSearch = Owner
End If
Dim SomeoneSlides As String
SomeoneSlides = ""
SomeoneSlides = ""
For Each oSl In ActivePresentation.Slides
For Each oShp In oSl.Shapes
If oShp.HasTextFrame Then
If InStr(1, oShp.TextFrame.TextRange.Text, strSearch, vbTextCompare) > 0 Then
slideList = slideList & "Slide " & oSl.SlideNumber & ": " & oShp.TextFrame.TextRange.Text & vbCrLf
SomeoneSlides = SomeoneSlides & oSl.SlideNumber & ","
End If
End If
Next
Next
'we now have "search" unique slides.
MsgBox slideList
End Function
*** I note the following works as I want - leaving my in power points seeing highlight boxes around the slides 1,2,5
Dim r1 As SlideRange
Set r1 = ActivePresentation.Slides.Range(Array(1,2, 5)) 'this works
r1.Select
*** However, when i try to create this programmatically i fail (only highlighting the last slide in the array)
'Call SelectSlides("1,2,") '(output from the search)
Sub SelectSlides(YourSlideList As String)
Dim slideArr() As String
'Dim slideNum As Integer
Dim selAry As String
ActiveWindow.ViewType = PpViewType.ppViewNormal
ActiveWindow.Panes(1).Activate
slideArr = Split(YourSlideList, ",")
Dim r1 As SlideRange
For i = 0 To (UBound(slideArr) - 1)
slideNum = CInt(slideArr(i))
selAry = selAry & slideNum
'For all slides selected - modify as needed....
With ActivePresentation.Slides.Range(slideNum)
'Ignore the default background settings.
.FollowMasterBackground = False
'And add a new background color and effect.
.Background.Fill.PresetGradient msoGradientHorizontal, 1, msoGradientDaybreak
End With
Set r1 = ActivePresentation.Slides.Range(Array(slideNum)) 'this works
Next
r1.Select
End Sub
'///this is now working
Sub SelectSlides(YourSlideList As String)
Dim slideArr() As String
'Dim slideNum As Integer
Dim selAry As String
Dim selAry2(99) As Long
ActiveWindow.ViewType = PpViewType.ppViewNormal
ActiveWindow.Panes(1).Activate
slideArr = Split(YourSlideList, ",")
' slideArr2() = Split(YourSlideList, ",")
For i = 0 To (UBound(slideArr) - 1)
slideNum = CInt(slideArr(i))
selAry = selAry & slideNum
selAry2(i) = slideNum
'For all slides selected - modify as needed....
With ActivePresentation.Slides.Range(slideNum)
'Ignore the default background settings.
.FollowMasterBackground = False
'And add a new background color and effect.
.Background.Fill.PresetGradient msoGradientHorizontal, 1, msoGradientDaybreak
End With
Next
Dim r1 As SlideRange
Set r1 = ActivePresentation.Slides.Range(selAry2)
r1.Select
End Sub

MS Word populate text after is inserted via VBA form

I have created word macro enabled template.
At opening form pops-up and user can fill in form. After pressing OK bookmarks inside document are updated and shown.
What I need is to populate entered values trough entire document on multiple locations. I have tried cross-referencing bookmarks but they are not updated with values entered in form.
image of opening form
Private Sub cancelBut_Click()
stInfo.Hide
End Sub
Private Sub Label11_Click()
End Sub
Private Sub OKbut_Click()
Dim katcest As Range
Set katcest = ActiveDocument.Bookmarks("katcest").Range
katcest.Text = Me.TextBox1.Value
Dim katopcina As Range
Set katopcina = ActiveDocument.Bookmarks("katopcina").Range
katopcina.Text = Me.TextBox2.Value
Dim zkcest As Range
Set zkcest = ActiveDocument.Bookmarks("zkcest").Range
zkcest.Text = Me.TextBox3.Value
Dim zkopcina As Range
Set zkopcina = ActiveDocument.Bookmarks("zkopcina").Range
zkopcina.Text = Me.TextBox4.Value
Dim zkulozak As Range
Set zkulozak = ActiveDocument.Bookmarks("zkulozak").Range
zkulozak.Text = Me.TextBox5.Value
Dim povrsina As Range
Set povrsina = ActiveDocument.Bookmarks("povrsina").Range
povrsina.Text = Me.TextBox6.Value
Dim vlasnik As Range
Set vlasnik = ActiveDocument.Bookmarks("vlasnik").Range
vlasnik.Text = Me.TextBox7.Value
Dim vladresa As Range
Set vladresa = ActiveDocument.Bookmarks("vladresa").Range
vladresa.Text = Me.TextBox8.Value
Dim datocevida As Range
Set datocevida = ActiveDocument.Bookmarks("datocevida").Range
datocevida.Text = Me.TextBox9.Value
Dim klasa As Range
Set klasa = ActiveDocument.Bookmarks("klasa").Range
klasa.Text = Me.TextBox10.Value
Dim urbroj As Range
Set urbroj = ActiveDocument.Bookmarks("urbroj").Range
urbroj.Text = Me.TextBox11.Value
Me.Repaint
Dim strDocName As String
Dim intPos As Integer
' Find position of extension in file name
strDocName = ""
intPos = InStrRev(strDocName, ".")
If intPos = 0 Then
' If the document has not yet been saved
' Ask the user to provide a file name
strDocName = InputBox("Upisi naziv " & _
"vaseg dokumenta.")
Else
' Strip off extension and add ".txt" extension
strDocName = Left(strDocName, intPos - 1)
strDocName = strDocName & ".docx"
End If
' Save file with new extension
ActiveDocument.SaveAs2 FileName:=strDocName, _
FileFormat:=wdFormatDocumentDefault
stInfo.Hide
infoForm.Show
End Sub

Outlook - VBA set signature to new Email ... so the signature can be changed via menu

I wrote a script where I add a signature from an htm file in the appData ... signature folder to a newly opened email.
My question is - how do i modify this VBA script to add that signature in a way so Outlook knows its a signature and the signature might be changed by a user via gui.
I assume it may have something to do with setting a "_MailAutoSig" bookmark, is that right?
Script looks like this and works so far:
Dim WithEvents m_objMail As Outlook.MailItem
Dim LODGIT_SUBJECT_IDENTIFIERS() As String
Private Sub Application_ItemLoad(ByVal Item As Object)
'MsgBox "Application_ItemLoad"
Select Case Item.Class
Case olMail
Set m_objMail = Item
End Select
End Sub
Private Sub m_objMail_Open(Cancel As Boolean)
'string array containing lodgit email subject identifiers (beginning string!!! of email subject)
LODGIT_SUBJECT_IDENTIFIERS = Split("Angebot von Bödele Alpenhotel,Angebot von,bestätigt Ihre Reservierung,Rechnung Nr.,Stornogutschrift für die Rechnung,Ausstehende Zahlung", ",")
Dim Application As Object
Dim oOutApp As Object, oOutMail As Object
Dim strbody As String, FixedHtmlBody As String
Dim Ret
Set Application = CreateObject("Outlook.Application")
'Change only Mysig.htm to the name of your signature
' C:\Users\nicole\AppData\Roaming\Microsoft\Signatures
Ret = Environ("appdata") & _
"\Microsoft\Signatures\AH Andrea kurz.htm"
If Ret = False Then Exit Sub
'~~> Use the function to fix image paths in the htm file
FixedHtmlBody = FixHtmlBody(Ret)
'CHECK FOR LODGIT IDENTIFIER
If myInStr(m_objMail.Subject, LODGIT_SUBJECT_IDENTIFIERS()) Then
Debug.Print "E-Mail as from Lodgit identified"
Dim str As String
Dim a As Object
str = Replace(m_objMail.Body, vbCrLf, "<br>")
str = Replace(str, vbNewLine, "<br>")
m_objMail.HTMLBody = "<html><body><span style='font-size:11.0pt;font-family:""Times New Roman"" '>" & str & "</span>" & FixedHtmlBody & "</body></html>"
End If
End Sub
'~~> Function to fix image paths in Signature .htm Files
Function FixHtmlBody(r As Variant) As String
Dim FullPath As String, filename As String
Dim FilenameWithoutExtn As String
Dim foldername As String
Dim MyData As String
'~~> Read the html file as text file in a string variable
Open r For Binary As #1
MyData = Space$(LOF(1))
Get #1, , MyData
Close #1
'~~> Get File Name from path
filename = GetFilenameFromPath(r)
'~~> Get File Name without extension
FilenameWithoutExtn = Left(filename, (InStrRev(filename, ".", -1, vbTextCompare) - 1))
'~~> Get the foldername where the images are stored
foldername = FilenameWithoutExtn & "-Dateien"
'~~> Full Path of Folder
FullPath = Left(r, InStrRev(r, "\")) & foldername
'~~> To cater for spaces in signature file name
'FullPath = Replace(FullPath, " ", "%20")
'~~> Replace incomplete path with full Path
FixHtmlBody = Replace(MyData, "AH%20Andrea%20kurz-Dateien", FullPath)
'FixHtmlBody = Replace(MyData, foldername, FullPath)
End Function
'~~> Gets File Name from path
Public Function GetFilenameFromPath(ByVal strPath As String) As String
If Right$(strPath, 1) <> "\" And Len(strPath) > 0 Then _
GetFilenameFromPath = GetFilenameFromPath(Left$(strPath, Len(strPath) - 1)) + Right$(strPath, 1)
End Function
'check if str contains on of the elements of a str array
Public Function myInStr(myString As String, a() As String) As Boolean
For Each elem In a
If InStr(1, myString, elem, vbTextCompare) <> 0 Then
myInStr = True
Exit Function
End If
Next
myInStr = False
End Function
Outlook looks for the "_MailAutoSig" bookmark. This needs to be done with Word Object Model, not by setting the HTMLBody property. Something along the lines:
wdStory = 6
wdMove = 0
Set objBkm = Nothing
Set objDoc = Inspector.WordEditor
Set objSel = objDoc.Application.Selection
'remember the cursor position
set cursorRange = objDoc.Range
cursorRange.Start = objSel.Start
cursorRange.End = objSel.End
If objDoc.Bookmarks.Exists("_MailAutoSig") Then
'replace old signature
Debug.Print "old signature found"
set objBkm = objDoc.Bookmarks("_MailAutoSig")
objBkm.Select
objDoc.Windows(1).Selection.Delete
ElseIf objDoc.Bookmarks.Exists("_MailOriginal") Then
' is there the original email? (_MailOriginal)
set objBkm = objDoc.Bookmarks("_MailOriginal")
objSel.Start = objBkm.Start-2 'give room for the line break before. It includes the line
objSel.End = objBkm.Start-2
Else
'insert at the end of the email
objSel.EndOf wdStory, wdMove
End If
'start bookmark
set bkmStart = objDoc.Bookmarks.Add("_tempStart", objSel.Range)
'end bookmark
set bkmEnd = objDoc.Bookmarks.Add("_tempEnd", objSel.Range)
bkmEnd.End = bkmEnd.End + 1
bkmEnd.Start = bkmEnd.Start + 1
objSel.Text = " "
set objBkm = objDoc.Bookmarks.Add("_MailAutoSig", bkmStart.Range)
objBkm.Range.insertFile "c:\Users\<user>\AppData\Roaming\Microsoft\Signatures\test.htm", , false, false, false
objBkm.Range.InsertParagraphBefore
objBkm.End = bkmEnd.Start - 1 'since we added 1 above for bkmEnd
objSel.Start = cursorRange.Start
objSel.End = cursorRange.End
bkmStart.Delete
bkmEnd.Delete

Add hyperlinks to linked images

I'm trying to add hyperlinks to images, which were added via IncludePicture fields.
For example, this is an image:
{ IncludePicture "C:\\Test\\Image 1.png" \d }
And so, it should be added hyperlink to it:
C:\\Test\\Image 1.png
After that, I can click on my image in document with mouse, and it will be opened in file manager.
Here is the code. For some reason, it doesn't properly work. How it should be fixed?
Sub AddHyperlinksToImages()
On Error Resume Next
Application.ScreenUpdating = False
Dim iShp As InlineShape
For Each iShp In ActiveDocument.InlineShapes
iShp.Hyperlink.Address = iShp.LinkFormat.SourceFullName 'Doesn't work
'Just for testing
'fullPath = iShp.LinkFormat.SourceFullName
'MsgBox fullPath
Next
Application.ScreenUpdating = True
End Sub
Please try this code.
Sub AddHyperlinksToImages()
' 22 Sep 2017
Dim Fld As Field
Dim FilePath As String
Dim Tmp As String
Dim i As Integer
Application.ScreenUpdating = False
ActiveDocument.Fields.Update
For Each Fld In ActiveDocument.Fields
With Fld
If InStr(1, Trim(.Code), "includepicture", vbTextCompare) = 1 Then
If .InlineShape.Hyperlink Is Nothing Then
i = InStr(.Code, Chr(34))
If i Then
FilePath = Replace(Mid(.Code, i + 1), "\\", "\")
i = InStr(FilePath, "\*")
If i Then FilePath = Left(FilePath, i - 1)
Do While Len(FilePath) > 1
i = Asc(Right(FilePath, 1))
FilePath = Left(FilePath, Len(FilePath) - 1)
If i = 34 Then Exit Do
Loop
If i > 1 Then ActiveDocument.Hyperlinks.Add .InlineShape, FilePath
End If
End If
End If
End With
Next Fld
Application.ScreenUpdating = True
End Sub

How to change link location in Word using VBA?

My Word document has links to Excel that, when displayed, look like this:
{ LINK Excel.SheetMacroEnabled.12 "C:\\Users\\Shawn\\projects\\Workbook1.xlsm" "Range1" }
I need my macro to be able to change this to a new path/file:
strNewFile = "C:\Users\Shawn\OtherFolder\Workbook2.xlsm".
(Note the single backslashes vs. the double ones.)
What's the simplest way? (Using Word 2013)
This post seemed to have the answer:
Linked Table in MS Word
Using this code:
Dim fieldCount As Integer, x As Long
With ActiveDocument
fieldCount = .Fields.Count
For x = 1 To fieldCount
With .Fields(x)
If .Type = 56 Then
'only update Excel links. Type 56 is an excel link
Debug.Print .LinkFormat.SourceFullName
.LinkFormat.SourceFullName = newfile '
.Update
.LinkFormat.AutoUpdate = False
DoEvents
End If
End With
Next x
End With
Sub changeSource()
Dim dlgSelectFile As FileDialog 'FileDialog object
Dim thisField As Field
Dim selectedFile As Variant 'must be Variant to contain filepath of selected item
Dim newFile As Variant
Dim fieldCount As Integer
'create FileDialog object as File Picker dialog box
Set dlgSelectFile = Application.FileDialog(FileDialogType:=msoFileDialogFilePicker)
With dlgSelectFile
'use Show method to display File Picker dialog box and return user's action
If .Show = -1 Then
'step through each string in the FileDialogSelectedItems collection
For Each selectedFile In .SelectedItems
newFile = selectedFile 'gets new filepath
Next selectedFile
Else 'user clicked cancel
End If
End With
Set dlgSelectFile = Nothing
'update fields
fieldCount = ActiveDocument.Fields.Count
For x = 1 To fieldCount
ActiveDocument.Fields(x).LinkFormat.SourceFullName = newFile
Next x
End Sub