Search code examples
excelvba

How to save Image independently in VBA module


I have below module to insert Image into a selected merged Cell and automatically resize the image to fit either Width or Height of that Cell. But I have a problem when sending this report to my customer, they can't see the images as my code inserted them as location path. The only solution I have now is to "save as pdf" then the customers can see the report.

Is there a way to save my Excel file with the images so they're still viewable when downloaded by my customers?

Sub INSERT_PIC()
    Dim MyMergeCell As Range
    Dim MyFile As String
    Dim MyPath As String
    '---------------------------------------------------------------------------
    '- SELECTED CELL
    Set MyMergeCell = ActiveCell
    '---------------------------------------------------------------------------
    '- OPEN THE FILE WITH GetOpenFilename()
    MyFile = Application.GetOpenFilename("Picture Files (*.bmp;*.jpg;*.tif;*.gif), *.bmp;*.jpg;*.tif;*.gif", , " GET PICTURE", , msoTrue)
    If MyFile = "False" Then Exit Sub
    '----------------------------------------------------------------------------
    '- INSERT THE FILE INTO THE WORKSHEET
    ActiveSheet.Pictures.Insert(MyFile).Select
    '----------------------------------------------------------------------------
    '- RESIZE PICTURE TO MERGE CELL. REFORMAT
    With MyMergeCell
        
        Dim r As Range, sel As Shape
Set sel = ActiveSheet.Shapes(Selection.Name)
sel.LockAspectRatio = msoTrue
Set r = Range(sel.TopLeftCell.MergeArea.Address)

Select Case (r.Width / r.Height) / (sel.Width / sel.Height)
    Case Is > 1
        sel.Height = r.Height
    Case Else
        sel.Width = r.Width
End Select

sel.Top = r.Top: sel.Left = r.Left
    End With
End Sub

Fail to view images from customer's computer


Solution

  • Looking at some traces on the Internet (e.g. at the SO question that Tim Williams linked to in the comments), it seems as if it is depending on the Excel version if the images are only linked or embedded when using Pictures.Insert.

    Instead, use Shapes.AddPicture, there you can define if you want to embed the picture or only link them. Another difference to the Insert-method is that you need already to specify the location, and that AddPicture is a function so you don't need to tinker around with Select.

    If you look at the answer https://stackoverflow.com/a/58500935/7599798, you are getting close to what you need. I combined the code from that answer with your code so that it deals with merged cells:

    Sub INSERT_PIC()
        Dim r As Range
        Set r = ActiveCell.MergeArea
        
        Dim MyFile As Variant
        MyFile = Application.GetOpenFilename("Picture Files (*.bmp;*.jpg;*.tif;*.gif), *.bmp;*.jpg;*.tif;*.gif", , " GET PICTURE", , msoTrue)
        If MyFile = False Then Exit Sub
        
        Dim sh As Shape
        Set sh = ActiveSheet.Shapes.AddPicture(MyFile, False, True, r.Left, r.Top, -1, -1)
        sh.LockAspectRatio = True
        If (r.Width / r.Height) / (sh.Width / sh.Height) > 1 Then
            sh.Height = r.Height
        Else
            sh.Width = r.Width
        End If
    End Sub