2

I am getting completely crazy about this issue, please help me.

I have made a shell script that writes in a text file the path of some images that are stored in a folder. Then I use an excel code to read each path and write it in an excel cell. I have then made a code that should take that path and use it to insert the picture. I have tried with Pictures.insert(path) and shapes.addpictures "path", but I have the same issue every time, the picture can't be loaded. What's weird, is that, if I manually insert the picture before and then delete it, the code will perfectly load the picture. But if it's the first time then no. The paths that I'm using look like that: "/Users/theodorebedos/Documents/code_tilly/new_pict_tilly/IMG_9040.jpg"

I'm using a mac, maybe that matters?

Private Sub Convert_Img()

Dim myPict As Picture
Dim PictureLoc As String
Dim EndPictRow, i As Integer
Dim StartPath As String


If Worksheets("Main").Cells(3, 1).Value <> "" Then
    EndPictRow = Worksheets("Main").Range("A2").End(xlDown).Row

    For i = 3 To EndPictRow
        PictureLoc = Worksheets("Main").Cells(i, 1).Value
        Worksheets("Main").Cells(i, 1).ClearContents
        Worksheets("Main").Cells(i, 1).ColumnWidth = 30
        Worksheets("Main").Cells(i, 1).RowHeight = 150
           ActiveSheet.Shapes.AddPicture PictureLoc, False, True, Worksheets("Main").Cells(i, 1).Left, Worksheets("Main").Cells(i, 1).Top, Worksheets("Main").Cells(i, 1).Width, Worksheets("Main").Cells(i, 1).Height

    Next i
End If

End Sub

Edit: When I use "Pictures.insert" or "shapes.addpicture path, true, true " I have no error message in VBA but I have in excel instead of my picture, a blank image with inside an error message like this: image

If I use "shapes.addpicture path, FALSE, true" then I have an error message like this but no image at all is loaded: image 2

And then an error 1004 like that: image3

And if I do the process to have image 1, then I save the document, reopen it, I'll have this directly: image 4

Thanks for you help. It will be much appreciated.

  • Is the `ActiveSheet` different from `Worksheets("Main")`? The use of `ActiveSheet` is never advisable unless you know exactly which one it is. (My question proves that you don't lol:). BTW `Dim EndPictRow` specifies a variant. If you want it to be an Integer you must specify (but it should be Long). From your description I suspect a issue with screen updating. Try to save your file after running the script and see if the picture shows when you re-open. – Variatus Mar 22 '20 at 01:24
  • Are you getting a run-time error or does code inserts an empty image in the worksheet? – DecimalTurn Mar 22 '20 at 03:27
  • Hi, thanks for your answers. @Variatus, There is only one sheet in my project so I know exactly which one is the activesheet (but everything is good to take, I tried to change it, but no change). I have saved my filed and then reopen it as you said and then I get the image4 in my description.(I have edited my question to be more precise). – Théodore Bedos Mar 22 '20 at 08:55
  • @DecimalTurn, can you check the images that I have just added to my description. It shows that with shapes.addpictures false, true, I have an error 1004. In other cases, I have no error. – Théodore Bedos Mar 22 '20 at 08:56
  • I have exactly identical issues with loading images via VBA on MacOS, and I am assuming that none of the answers given below provide a solution. As it turns out this seems to be a permission problem specific to MacOS. – Michael Jun 08 '22 at 18:48

3 Answers3

1

I hope someone will benefit from this old thread. As it turns out this is some sort of a permission issue also noted already in one of the comments, possibly only occurring with Excel 16 macros on OSX.

It seems like Excel is lacking the permissions to access the resources linked and is not asking for them. We need to grant permissions to all files in the folder. The following code demonstrates how to achieve this, given the identifier to build the paths is in Column A2:20. Run this macro (adjust the way the path is built), then grant access once the dialogue appears:

Sub GrantAccess()
    Dim cName As Variant
    Dim files() As Variant
    Set xRange = ActiveSheet.Range("A2:A20")
        For Each cell In xRange
                 ReDim Preserve files(1 To cell.Row - 1)
                 cName = "/Users/adjust-your-path/path" & Cells(cell.Row, "A") & "_thumb_600.png"
                 files(cell.Row - 1) = cName
        Next
        fileAccessGranted = GrantAccessToMultipleFiles(files)
End Sub

Code used:

Sub URLPICInsertMM()
    Dim cShape As Shape
    Dim cRange As Range
    Dim cColumn As Long
    Dim cName As String
    Dim img As Picture
    Application.ScreenUpdating = False
    Set xRange = ActiveSheet.Range("B2:B10")
    For Each cell In xRange
        'cName = Application.GetOpenFilename(Title:="Select Picture To Be Imported")
        ' files are located in thumbs sub-directory       
        cName = "/Users/.../IonChannels/thumbs/" & Cells(cell.Row, "A") & "_thumb_300.png"
        Set img = ActiveSheet.Pictures.Insert(cName)
        img.Select
        Set cShape = Selection.ShapeRange.Item(1)
        If cShape Is Nothing Then GoTo line22
        Cells(cell.Row, "C").Value = "file://" & cName
        Set cRange = Cells(cell.Row, cell.Column)
        With cShape
            .LockAspectRatio = msoTrue
            'If .Width > cRange.Width Then .Width = cRange.Width
            If .Height > cRange.Height Then .Height = cRange.Height
            .Top = cRange.Top + (cRange.Height - .Height)
            .Left = cRange.Left + (cRange.Width - .Width)
        End With
line22:
        Set cShape = Nothing
        Range("T2").Select
    Next
    Application.ScreenUpdating = True
End Sub

Edit:

Evidence:

I created a simple test sheet (the idea is to load some protein visualization thumbs into an excel sheet) with an identifier in Column A, image file descriptors are constructed from the identifier + path and file extension. The image is inserted into Column B and the file descriptor as text into Column C.

When I ran the macro for the first time, only the first image was loaded. Excel formats the file descriptor as a hyperlink. When clicking the file:///... link, Excel opens a dialog that asks to grant permissions to that file (screenshot). If I grant access and accept warnings, then run the macro again, the image appears.

enter image description here

After running macro again, image is displayed: enter image description here

Michael
  • 232
  • 2
  • 12
0

I streamlined your code so it becomes possible to see what it's doing. Note that I avoided reading values from the cell's properties which were just set or are obvious.

  1. Once the column width has been set, the width of all cells in it are the same.
  2. The Left property of all cells in a column is always the same.
  3. If the column is column A, the Left is always 0.

Of course, what you tried to achieve is to enter a value only once. That is good practice but to read properties from the sheet is slow. The faster way - less code volume and better readable, too - is to declare a constant at the top and use that name in the code.

So you end up with this code.

Private Sub Convert_Img()

    Const ClmWidth As Single = 30
    Const RowHight As Single = 150

    Dim EndPictRow As Long, R As Long
    ' sorry, I recommend i for arrays and R for rows (C for columns)


    With Worksheets("Main")
        ' End(xlDown) will find the first blank cell below the base cell.
        '   There might be more filled cells further down.
        ' End(xlUp) will find the first used cell above the base cell
        '   disregarding more blanks above that one.
        EndPictRow = .Cells(.Rows.Count, "A").End(xlUp).Row

        ' no need to set the column width multiple times in the loop
        .Columns(1).ColumnWidth = ClmWidth

        ' this loop will never run if R < EndPicRow
        For R = 3 To EndPictRow
            With .Cells(R, 1)
                .RowHeight = RowHight
                ' this will work only once:-
                .Worksheet.Shapes.AddPicture CStr(.Value), False, True, 0, .Top, ClmWidth, RowHight
            End With
        Next R
    End With
End Sub

The reason why it works only once becomes quite obvious. The new picture takes its source path from the cell's Value. Of course, once you insert a picture (image) in the cell that value can't be the path (string) anymore. If you run the code a second time it will fail. However, if that is your need, it should be possible to extract the path from the formula that defines the picture in the cell. Given that the picture itself isn't present at that location the formula should either hold the path or a reference to a location within the workbook's background data, depending upon how it was loaded.

Variatus
  • 14,293
  • 2
  • 14
  • 30
  • Hello, Thanks for your help. But I think that you didn't understand my problem. You said: "the reason it works only once becomes...", but that's the problem it doesn't work at all, never. Even with your code, I tried and I get the same message than on my image3 (link in my question). The only way it could work, is if I manually insert the picture before. If a picture as already been inserted manually once on the sheet then I can delete it and it will be inserted succesfully if I use my code. – Théodore Bedos Mar 22 '20 at 12:16
  • But yes, I agree, my code is full of little error that slow it down and it's not perfect, but I really don't think the error comes from that. – Théodore Bedos Mar 22 '20 at 12:21
  • Please focus on the `Value` property. Initially, if it is a file name with a full path, it should work. If you are saving the picture into the workbook (you can try to just save the reference for external storage), Excel may remember the location. Look at the cell `Value` after the macro has run. It doesn't contain a path string anymore. I don't know what you are trying to do but it's the content of that cell which is causing the malfunction you complain about. Try keeping the path in another cell, reinstate the `ClearContents` for the target cell and try running the code several times. – Variatus Mar 22 '20 at 13:12
  • Sorry but I don't understand. I have tried to write my paths on another column thta I don't clear and I have excately the same issue. If I keep running my code again and agian, I just keep having error 1004 if I use addpictures, and if I use Pictures.insert I just add more blank pictures like my "image1" on top of each other. No matter if I save the document or not in between. – Théodore Bedos Mar 22 '20 at 17:21
  • The code reads the path from the cell and then inserts the picture in its place. Therefore on second run it shouldn't work. The question shifts from why it doesn't work to why it does. However, if there is a path in the cell it should work. You now state for the first time that you get a blank picture. Before you said you get none. That points the finger at the path. The requirement is for a file name with full path. – Variatus Mar 23 '20 at 01:21
  • 1
    To ensure progress, please run the code on a single cell (disable the loop). Make sure that you have a complete path, starting with the drive letter, in the cell. Test the path and file name using `Dir()` to make sure it has no typos in it. Run the code only once. Let us know the result. – Variatus Mar 23 '20 at 01:26
0

Ok, so it's not perfect yet, but I put the loop off and I used Dir() as you said @Variatus.A pop-up window like this opened when I executed the command Dir(). It asked me the authorisation to access the file. I pressed yes and then it worked. It worked but only for that file. So I guess, I am on the right way now and I need to find how to give access to all the files in that folder before running the code. I can't do it for all of them. Thank you very much.

  • I noticed you deleted you other answer, personally I would have suggested to combine the two in order to show to whole reasoning process towards the solution. That would be very helpful if someone with the same problem find this question later. – DecimalTurn Mar 23 '20 at 22:26