MS Word Caption with the Image Name - vba

The code below works like a charm. It allows the user to pick a folder with .jpgs and other image types into a 2 image per page. The Current code just captions the image as "Picture". What I am needing assistance with is getting the image name as caption minus the .jpg. Any direction would be great:
Sub AddPic()
Dim fd As FileDialog
Dim oTbl As Table
Dim oILS As InlineShape
Dim vrtSelectedItem As Variant
'''''''''''''''
'Add a 1 row 2 column table to take the images
'''''''''''''''
Set oTbl = Selection.Tables.Add(Selection.Range, 4, 1)
With oTbl
.AutoFitBehavior (wdAutoFitWindow)
End With
'''''''''''''''
Set fda = Application.FileDialog(msoFileDialogFilePicker)
With fda
.Title = "Select image files and click OK"
.Filters.Add "Images", "*.gif; *.jpg; *.jpeg; *.bmp; *.tif; *.png"
.FilterIndex = 2
If .Show = -1 Then
CaptionLabels.Add Name:="Picture"
For Each vrtSelectedItem In .SelectedItems
With Selection
Set oILS = .InlineShapes.AddPicture(FileName:= _
vrtSelectedItem, LinkToFile:=False, SaveWithDocument:=True, _
Range:=Selection.Range)
oILS.Range.InsertCaption Label:="Picture", TitleAutoText:="", Title:="", _
Position:=wdCaptionPositionBelow, ExcludeLabel:=0
.MoveRight wdCell, 1
End With
Next vrtSelectedItem
If Len(oTbl.Rows.Last.Cells(1).Range) = 2 Then oTbl.Rows.Last.Delete
Set fd = Nothing
End If
End With
'''''''''''''''
For Each pic In ActiveDocument.InlineShapes
With pic
.LockAspectRatio = msoFalse
If .Width > .Height Then ' horizontal
.Width = InchesToPoints(5.5)
.Height = InchesToPoints(3.66)
Else ' vertical
.Width = InchesToPoints(5.5)
End If
End With
Next
'''''''''''''''
Selection.WholeStory
Selection.Font.Bold = wdToggle
Selection.Font.Bold = wdToggle
Selection.Font.Color = wdColorBlack
'''''''''''''''
End Sub

It appears vrtSelectedItem provides the information that's required, so the only problem is cutting off the file extension.
This can be done by string manipulation. In the code snippet below, taken from the question, the location of the . in the file name is ascertained, as well as the length of the file name. The Mid function is then used to extract the text to the left of that point.
Dim dotPos as long, lenName as Long
Dim capt as String
For Each vrtSelectedItem In .SelectedItems
dotPos = Instr(vrtSelectedItem, ".")
lenName = Len(vrtSelectedItem)
capt = Mid(vrtSelectedItem, lenName + (dotPos - 1 - lenName ))
With Selection
Set oILS = .InlineShapes.AddPicture(FileName:= _
vrtSelectedItem, LinkToFile:=False, SaveWithDocument:=True, _
Range:=Selection.Range)
oILS.Range.InsertCaption Label:="Picture", TitleAutoText:="", Title:=capt, _
Position:=wdCaptionPositionBelow, ExcludeLabel:=0
.MoveRight wdCell, 1
End With
Next vrtSelectedItem

Related

How get i get an AddedPicture center on a page word

To get around the fact that the manual way to insert a pdf in a word don't give really good quality result.
I'm trying to insert pictures that have been nicely converted from a pdf to png with Imagemagick in a word with a macro.
The moment where i struggle is when i want the picture to get in a middle of each page and don't overlap each over.
I come up with this but i don't understand why it seems that AllowOverlap and wdShapeCenter do nothing while wdWrapTopBottom work properly. The picture get stuck to the top-left corner'
Sub Test()
Dim objShape As Shape
strPath = "Some.png"
'insert the image
Set objShape = ActiveDocument.Shapes.AddPicture( _
FileName:=strPath, LinkToFile:=False, _
SaveWithDocument:=True)
objShape.WrapFormat.AllowOverlap = False
objShape.Top = WdShapePosition.wdShapeCenter
objShape.WrapFormat.Type = wdWrapTopBottom
End Sub
I tried to use Selection.InlineShapes.AddPicture to resolve the overlap problem but i can't get the picture move from the top-left corner neither.
Thanks for your help
For example:
Sub Demo()
Application.ScreenUpdating = False
Dim Shp As Shape
With Dialogs(wdDialogInsertPicture)
.Display
If .Name <> "" Then
Set Shp = ActiveDocument.Shapes.AddPicture(FileName:=.Name, _
LinkToFile:=False, SaveWithDocument:=True, Anchor:=Selection.Range)
With Shp
.LockAspectRatio = True
.Height = InchesToPoints(2)
.RelativeHorizontalPosition = wdRelativeHorizontalPositionMargin
.Left = wdShapeCenter
.RelativeVerticalPosition = wdRelativeVerticalPositionMargin
.Top = wdShapeCenter
.WrapFormat.AllowOverlap = False
End With
End If
End With
Application.ScreenUpdating = True
End Sub
With the above code, the inserted pic will be positioned in the center of the page. If there's already one centered there, the existing pic will be pushed down.
In light of your additional information, you should use something like:
Sub Demo()
Application.ScreenUpdating = False
Dim iShp As InlineShape, sWdth As Single, sHght As Single
With Dialogs(wdDialogInsertPicture)
.Display
If .Name <> "" Then
Set Shp = .InlineShapes.AddPicture(FileName:=.Name, _
LinkToFile:=False, SaveWithDocument:=True, Range:=Selection.Range)
With ActiveDocument.PageSetup
sWdth = .PageWidth - .LeftMargin - .RightMargin
sHght = .PageHeight - .TopMargin - .LeftMargin
End With
With iShp
.LockAspectRatio = True
.Width = sWdth
If .Height > sHght Then .Height = sHght
End With
End If
End With
Application.ScreenUpdating = True
End Sub
Finaly with your help I come up with this.
It center and place on it's own page pictures from a Folder.
Sub Folder_Picture_To_Word()
Dim shp As Shape
Dim intResult As Integer
Dim strPath As String
Dim strFolderPath As String
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
'the dialog is displayed to the user
intResult = Application.FileDialog(msoFileDialogFolderPicker).Show
'checks if user has cancled the dialog
If intResult <> 0 Then
'dispaly message box
strFolderPath = Application.FileDialog(msoFileDialogFolderPicker _
).SelectedItems(1)
'Create an instance of the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Get the folder object
Set objFolder = objFSO.GetFolder(strFolderPath)
'loops through each file in the directory and prints their names and path
For Each objFile In objFolder.Files
'get file path
strPath = objFile.Path
Selection.InsertAfter ChrW(12)
'insert the image
Set shp = ActiveDocument.Shapes.AddPicture(FileName:=strPath, _
LinkToFile:=False, SaveWithDocument:=True, Anchor:=Selection.Range)
With shp
'.LockAspectRatio = True
'.Height = InchesToPoints(8)
.RelativeHorizontalPosition = wdRelativeHorizontalPositionMargin
.Left = wdShapeCenter
.RelativeVerticalPosition = wdRelativeVerticalPositionMargin
.Top = wdShapeCenter
.WrapFormat.Type = wdWrapTopBottom
.WrapFormat.AllowOverlap = False
End With
'Go to next Page to get ready for a new picture
Selection.GoTo What:=wdGoToPage, Which:=wdGoToNext
Next objFile
Selection.GoTo What:=wdGoToPage, Which:=wdGoToPrevious 'Go to second last page
'To delete the extra jump page made in the loop
Selection.Delete
End If
End Sub

Text Box Rotation Issue

I am trying to write a macro to insert a custom watermark in my Word document.
The code works perfectly for the first two pages of the document but thereafter the the Textbox does not rotate to -45 as mentioned in the code
What am I doing wrong?
Sub CustomWatermark()
Dim activeDoc As Document
Dim rngDoc As Range
Dim shpTextBox As Shape
Dim lngPages As Long
Dim i As Long
Dim strWatermark As String
Set activeDoc = ActiveDocument
lngPages = activeDoc.Range.Information(wdNumberOfPagesInDocument)
strWatermark = InputBox("Enter Watermark")
With activeDoc
For i = 1 To lngPages
Set rngDoc = .GoTo(What:=wdGoToPage, Name:=i)
rngDoc.Collapse wdCollapseStart
Set shpTextBox = .Shapes.AddTextbox(Orientation:=msoTextOrientationHorizontal, _
Left:=InchesToPoints(1), _
Top:=InchesToPoints(4), _
Width:=InchesToPoints(6), _
Height:=InchesToPoints(2), _
Anchor:=rngDoc)
With shpTextBox
.Line.Visible = msoFalse
.Rotation = -45
.WrapFormat.Type = wdWrapBehind
.TextFrame.HorizontalAnchor = msoAnchorCenter
.TextFrame.VerticalAnchor = msoAnchorMiddle
With .TextFrame.TextRange
.Font.AllCaps = True
.Font.Size = "60"
.Font.ColorIndex = wdGray25
.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Text = strWatermark
End With
End With
Next
End With
End Sub
It looks that, selecting all their range and doing rotation at once, works...
Sub CustomWatermarkBis()
Dim activeDoc As Document, rngDoc As Range, shpTextBox As Shape
Dim lngPages As Long, i As Long, strWatermark As String, shR As ShapeRange
Dim arrRot As Variant, k As Long
Set activeDoc = ActiveDocument
lngPages = activeDoc.Range.Information(wdNumberOfPagesInDocument)
ReDim arrRot(0 To lngPages - 1)
strWatermark = InputBox("Enter Watermark Text")
With activeDoc
For i = 1 To lngPages
Set rngDoc = .GoTo(What:=wdGoToPage, Name:=i)
rngDoc.Collapse wdCollapseStart
Set shpTextBox = .Shapes.AddTextbox(Orientation:=msoTextOrientationHorizontal, _
Left:=InchesToPoints(1), _
Top:=InchesToPoints(4), _
Width:=InchesToPoints(6), _
Height:=InchesToPoints(2), _
Anchor:=rngDoc)
With shpTextBox.TextFrame.TextRange
.Font.AllCaps = True
.Font.Size = "60"
.Font.ColorIndex = wdGray25
.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Text = strWatermark
End With
shpTextBox.Name = "T" & i
arrRot(k) = shpTextBox.Name: k = k + 1
Next
Set shR = .Shapes.Range(arrRot)
End With
With shR
.Select
.Line.Visible = msoFalse
.Rotation = -45
.WrapFormat.Type = wdWrapBehind
.TextFrame.HorizontalAnchor = msoAnchorCenter
.TextFrame.VerticalAnchor = msoAnchorMiddle
End With
Selection.Collapse
End Sub
Re-ordering your code to add the text before changing the rotation should solve the issue. It certainly does for me in Word 365.
EDIT: That approach worked for me exactly twice and now I can't repeat it. Adding the text box to the header does work reliably though, and results in a much tidier document.
Sub CustomWatermarkInHeader()
Dim activeDoc As Document
Dim rngDoc As Range
Dim strWatermark As String
Dim docSection As Section
Dim shpTextBox As Shape
Set activeDoc = ActiveDocument
strWatermark = InputBox("Enter Watermark")
With activeDoc
For Each docSection In .Sections
Set rngDoc = docSection.Headers(wdHeaderFooterPrimary).Range
rngDoc.Collapse wdCollapseStart
Set shpTextBox = .Shapes.AddTextbox(Orientation:=msoTextOrientationHorizontal, _
Left:=InchesToPoints(1), _
Top:=InchesToPoints(4), _
Width:=InchesToPoints(6), _
Height:=InchesToPoints(2), _
Anchor:=rngDoc)
With shpTextBox
With .TextFrame
.HorizontalAnchor = msoAnchorCenter
.VerticalAnchor = msoAnchorMiddle
With .TextRange
.Font.AllCaps = True
.Font.Size = "60"
.Font.ColorIndex = wdGray25
.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Text = strWatermark
End With
End With
.Line.Visible = msoFalse
.Rotation = -45
.WrapFormat.Type = wdWrapBehind
End With
Next
End With
End Sub
However, you may want to consider:
adding the text box to the header instead of cluttering your document with a text box on every page. You will achieve the same result with fewer text boxes.
Using the built-in functionality to add a custom watermark. You can find this on the Design tab of the ribbon.
Instead of:
.Rotation = -45
Try:
.ThreeD.IncrementRotationZ -45
https://learn.microsoft.com/en-us/office/vba/api/word.threedformat

Excel VBA ExportAsFixedFormat Not Printing Margins

I have a simple Sub to save a range as a PDF in a user specified folder. The problem is that PDF it produces has 0 margin at top. I need a 0.25" margin.
What am I doing wrong?
Private Sub btnPrintJobWorksheet_Click()
Dim folderPath As String, filePath As String, fileName As String, jobNumber, rng As String
Dim ws As Worksheet
'Get the Job Number and create the File Name
jobNumber = ThisWorkbook.Names("JOBNUMBER").RefersToRange.Value
fileName = "Job Worksheet - " & jobNumber & ".pdf"
'Allow the user to select the folder to save to
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = -1 Then
folderPath = .SelectedItems(1)
filePath = folderPath & "\" & fileName
End If
End With
'Retrieve the Print Area
Set ws = ThisWorkbook.ActiveSheet
rng = CStr(ws.PageSetup.printArea)
'Set the Page Margins
With ws.PageSetup
.CenterHorizontally = True
.TopMargin = 0.25
.RightMargin = 0.2
.BottomMargin = 0.25
.LeftMargin = 0.2
.HeaderMargin = 0.1
.Zoom = False
.FitToPagesTall = 1
.FitToPagesWide = 1
End With
'If No Print Area was found, then set the Print Area range to its default value
If (Len(rng) < 2) Then
rng = "$B$1:$L$51"
End If
'If we have a File Path and we have a range, then save the PDF
If Len(filePath) > 0 And Len(rng) > 2 Then
ws.Range(rng).ExportAsFixedFormat _
Type:=xlTypePDF, fileName:=filePath, Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, openAfterPublish:=True
End If
Set ws = Nothing
End Sub
TopMarginproperty accepts points, not inches
so you have to "translate" inches to points
TopMargin = Application.InchesToPoints(0.25)
the same applies for other margins properties

Word Macro: Change page orientation depending on image ratio

My macro currently does the following:
It adds a header to a Word document, then reads image files from a specific folder from the HDD and adds them to the same document with the name of the file below the image and a page break after each image. To ensure that the name doesn't get pushed to the next page (if the image fills the whole page), I set the bottom margin to a higher value before adding the image and the name and then set the margin back to the original value. This way the image is a little bit smaller and leaves enough space for the name.
What I now want to add to this:
Switch the orientation of the page depending on the images' width and height and add a manual page break, so I can have multiple orientations in the same document.
But I'm already failing at the first thing:
How do I get the width/height/ration of the images before adding them
to the document (Img.Width doesn't seem to exist in Word)? I don't care what kind of information it is, as long as it tells me if the image is landscape or portrait.
How do I add a manual page break (Chr(12) just jumps to the next page without adding an actual break)?
Adding a manual page break also means that my header text won't be used afterwards but how do I set it for the new "Section"? I'm guessing it's not still ActiveDocument.Sections(1) then, is it?
My code (just the image import Sub):
Sub ImportImages(path As String)
Dim fs As Object
Dim ff As Variant
Dim Img As Variant
Dim i As Long
Dim fsize As Long
Dim bottomMarginOriginal As Single
Dim vertical As Boolean
Set fs = CreateObject("Scripting.FileSystemObject")
Set ff = fs.GetFolder(path).Files
i = 0
fsize = ff.Count
vertical = True
With ActiveDocument
bottomMarginOriginal = .PageSetup.BottomMargin
.PageSetup.BottomMargin = bottomMarginOriginal + Application.CentimetersToPoints(1) 'Add 1cm to margin
For Each Img In ff
Select Case Right(Img.name, 4)
Case ".bmp", ".jpg", ".gif", ".png", "tiff", ".tif"
If i <> 0 Then
.Characters.Last.InsertBefore Chr(12) 'Add page break before adding the img
Debug.Print "Width: " & Img.Width 'Error message: Doesn't exist!
Else
.Sections(1).Headers(wdHeaderFooterPrimary).Range.Text = "test text"
.PageSetup.Orientation = wdOrientLandscape 'TODO: Check the img ratio
vertical = False
End If
i = i + 1
.Characters.Last.InlineShapes.AddPicture filename:=Img 'Add the img
.Characters.Last.InsertBefore Chr(11) & Img.name 'Add a line break and the img name
End Select
Next
End With
ActiveDocument.PageSetup.BottomMargin = bottomMarginOriginal
End Sub
Edit:
This code does add section breaks but it seems like it sets the orientation for the whole document, not just the current section, so I end up with the same orientation on all pages, plus the images are only added in the very last section without any page/section breaks in between. How do I fix this?
Sub ImportImages(path As String)
Dim fs As Object
Dim ff As Variant
Dim img As Variant
Dim i As Long
Dim fsize As Long
Dim bottomMarginOriginal As Single
Dim topMarginOriginal As Single
Dim vertical As Boolean
Dim objShell As New Shell
Dim objFolder As Folder
Dim objFile As ShellFolderItem
Dim width As Integer
Dim height As Integer
Set fs = CreateObject("Scripting.FileSystemObject")
Set ff = fs.GetFolder(path).Files
i = 0
fsize = ff.Count
vertical = True
Set objFolder = objShell.NameSpace(path)
With ActiveDocument
bottomMarginOriginal = .PageSetup.BottomMargin
topMarginOriginal = .PageSetup.TopMargin
For Each img In ff
Select Case Right(img.name, 4)
Case ".bmp", ".jpg", ".gif", ".png", "tiff", ".tif"
Set objFile = objFolder.ParseName(img.name)
width = objFile.ExtendedProperty("{6444048F-4C8B-11D1-8B70-080036B11A03} 3")
height = objFile.ExtendedProperty("{6444048F-4C8B-11D1-8B70-080036B11A03} 4")
If width > height Then
If vertical = False Then 'Already landscape -> just add page break
.Characters.Last.InsertBefore Chr(12)
Else 'Set to landscape
Selection.InsertBreak Type:=wdSectionBreakNextPage
.PageSetup.Orientation = wdOrientLandscape
.PageSetup.TopMargin = topMarginOriginal 'Adjust margins to new orientation
.PageSetup.RightMargin = bottomMarginOriginal
.PageSetup.BottomMargin = bottomMarginOriginal
.PageSetup.LeftMargin = bottomMarginOriginal
.Sections(1).Headers(wdHeaderFooterPrimary).Range.Text = "test " & i 'Set header
vertical = False
End If
ElseIf height > width Then
If vertical = True Then 'Already portrait -> just add page break on page 2+
If i <> 0 Then
.Characters.Last.InsertBefore Chr(12)
End If
Else 'Set to portrait
Selection.InsertBreak Type:=wdSectionBreakNextPage
.PageSetup.Orientation = wdOrientPortrait
.PageSetup.TopMargin = topMarginOriginal 'Adjust margins to new orientation
.PageSetup.RightMargin = bottomMarginOriginal
.PageSetup.BottomMargin = bottomMarginOriginal
.PageSetup.LeftMargin = bottomMarginOriginal
.Sections(1).Headers(wdHeaderFooterPrimary).Range.Text = "test " & i 'Set header
vertical = True
End If
Else
If i <> 0 Then
.Characters.Last.InsertBefore Chr(12)
End If
End If
.PageSetup.BottomMargin = bottomMarginOriginal + Application.CentimetersToPoints(1) 'Add 1cm to the bottom margin
i = i + 1
.Characters.Last.InlineShapes.AddPicture filename:=img
.Characters.Last.InsertBefore Chr(11) & img.name
.PageSetup.BottomMargin = bottomMarginOriginal 'Reset bottom margin to default
End Select
Next
End With
End Sub
You don't need to get the image dimensions beforehand. Try something along the lines of:
Sub AddPics()
Application.ScreenUpdating = False
Dim i As Long, StrTxt As String, Rng As Range, vCol
Dim sAspect As Single, sLndWdth As Single, sLndHght As Single
Dim sMgnL As Single, sMgnR As Single, sMgnT As Single, sMgnB As Single, sMgnG As Single
'Select and insert the Pics
With Application.FileDialog(msoFileDialogFilePicker)
.Title = "Select image files and click OK"
.Filters.Add "Images", "*.gif; *.jpg; *.jpeg; *.bmp; *.tif; *.png"
.FilterIndex = 2
If .Show = -1 Then
Set vCol = .SelectedItems
Else
Exit Sub
End If
End With
With ActiveDocument
'Create a paragraph Style with 0 space before/after & centre-aligned
On Error Resume Next
.Styles.Add Name:="Pic", Type:=wdStyleTypeParagraph
With .Styles("Pic").ParagraphFormat
.Alignment = wdAlignParagraphCenter
.SpaceAfter = 0
.SpaceBefore = 0
End With
On Error GoTo 0
With .PageSetup
sMgnL = .LeftMargin: sMgnR = .RightMargin: sMgnT = .TopMargin: sMgnB = .BottomMargin: sMgnG = .Gutter
End With
Set Rng = Selection.Range
With Rng
.Paragraphs.Last.Style = "Pic"
For i = 1 To vCol.Count
.InsertAfter vbCr
.Characters.Last.InsertBreak Type:=wdSectionBreakNextPage
.InlineShapes.AddPicture FileName:=vCol(i), LinkToFile:=False, SaveWithDocument:=True, Range:=.Characters.Last
'Get the Image name for the Caption
StrTxt = Split(Split(vCol(i), "\")(UBound(Split(vCol(i), "\"))), ".")(0)
'Insert the Caption below the picture
.Characters.Last.InsertBefore Chr(11) & StrTxt
Next
.Characters.First.Text = vbNullString
.Characters.Last.Previous.Text = vbNullString
For i = 1 To .InlineShapes.Count
With .InlineShapes(i)
'Reorient pages for landscape pics
If .Height / .Width < 1 Then
With .Range.Sections(1).PageSetup
.Orientation = wdOrientLandscape
.LeftMargin = sMgnL: .RightMargin = sMgnR: .TopMargin = sMgnT: .BottomMargin = sMgnB: .Gutter = sMgnG
sLndWdth = .PageWidth - sMgnL - sMgnR - sMgnG
sLndHght = .PageHeight - sMgnT - sMgnB
End With
.LockAspectRatio = True
.ScaleHeight = 100
If .Height > sLndHght Then .Height = sLndHght
If .Width > sLndWdth Then .Width = sLndWdth
End If
End With
Next
End With
End With
Application.ScreenUpdating = True
End Sub

Insert Multiple Images As Comments Into Multiple Cells Using VBA Giving Subscript Out Of Range Error (9)

I'm getting the subscript out of range (error 9) when trying to insert multiple images into a comment in multiple cells. The idea of the VBA code is for me to be able to select multiple cells in workbook, then select multiple images, and it will add the images in order as a comment to each cell in order.
In order to do this I first try to go through the selected images in the file dialog window with a For loop and add them to the TheFile array. Then I try to use another For loop to add the image in the array position of j into the current cell and move on to the next cell and do the same.
Any idea what is causing the subscript out of range error? My code below:
Sub AddImageTo()
Dim TheFile() As String
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = True 'Only one file
.InitialFileName = CurDir 'directory to open the window
.Filters.Clear 'Cancel the filter
.Filters.Add Description:="Images", Extensions:="*.*", Position:=1
.Title = "Choose image"
If .Show = -1 Then
For i = 1 To .SelectedItems.Count
TheFile(i) = .SelectedItems(i)
Next i
Else: TheFile(1) = 0
End If
End With
'No file selected
If TheFile(1) = 0 Then
MsgBox ("No image selected")
Exit Sub
End If
Set objImage = CreateObject("WIA.ImageFile")
objImage.LoadFile TheFile
For j = 1 To UBound(TheFile)
For Each cell In Selection
With ActiveCell
.AddComment
With .Comment
With .Shape
.Fill.UserPicture TheFile(j)
.Height = objImage.Height * 0.45
.Width = objImage.Width * 0.45
End With
End With
End With
Next cell
Next j
End Sub
The issue is if you Dim TheFile() As String your array has no defined dimension and therefore you cannot access any item in the array like TheFile(1) = 0.
Here is an example on how to use the FileDialog for a multiselect
Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.InitialFileName = CurDir
.InitialView = msoFileDialogViewList
.AllowMultiSelect = True
.Filters.Clear
.Filters.Add Description:="Images", Extensions:="*.*", Position:=1
.Title = "Choose image"
End With
Dim FileChosen As Integer
FileChosen = fd.Show 'show dialog
If FileChosen = -1 Then
Dim AddImagesRange As Range
Set AddImagesRange = Selection
'check if cells count matches files count
If AddImagesRange.Cells.Count <> fd.SelectedItems.Count Then
MsgBox "Count of seletced cells does not match count of images"
Exit Sub
End If
Dim i As Long: i = 1
Dim objImage As Object
Dim Cell As Range
For Each Cell In AddImagesRange
Set objImage = CreateObject("WIA.ImageFile")
objImage.LoadFile fd.SelectedItems(i)
Cell.AddComment
With Cell.Comment.Shape 'avoid cascaded with statements
.Fill.UserPicture fd.SelectedItems(i)
.Height = objImage.Height * 0.45
.Width = objImage.Width * 0.45
End With
i = i + 1
Set objImage = Nothing
Next Cell
Else
MsgBox ("No image selected")
Exit Sub
End If
Try this.
Sub AddImageTo()
Dim TheFile() As String
Dim Cell As Range
Dim rngPic() As Range
Dim i As Integer, k As Integer, n As Integer, j As Integer
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = True 'Only one file
.InitialFileName = CurDir 'directory to open the window
.Filters.Clear 'Cancel the filter
.Filters.Add Description:="Images", Extensions:="*.*", Position:=1
.Title = "Choose image"
.Show
For i = 1 To .SelectedItems.Count
k = k + 1
ReDim Preserve TheFile(1 To k)
TheFile(k) = .SelectedItems(i)
Next i
End With
'No file selected
If k = 0 Then
MsgBox ("No image selected")
Exit Sub
End If
Set objImage = CreateObject("WIA.ImageFile")
objImage.LoadFile TheFile(1)
For Each Cell In Selection
n = n + 1
ReDim Preserve rngPic(1 To n)
Set rngPic(n) = Cell
Next Cell
For j = 1 To UBound(TheFile)
If j > n Then Exit Sub
With rngPic(j)
.ClearComments
.AddComment
With .Comment
With .Shape
.Fill.UserPicture TheFile(j)
.Height = objImage.Height * 0.45
.Width = objImage.Width * 0.45
End With
End With
End With
Next j
End Sub