View Full Version : Linked Picture; Add to Comment
Kwong
07-17-2008, 02:08 AM
Dear All,
 
I'm preparing an organization chart with photos.
 
I have a list (or a column) with the full path file names of the pictures. Say in 'Sheet 2' Column A.
 
I want to display all those pictures in the particular cells under the organization chart. Say in 'Sheet 1'.
 
Anyone could help me please.
 
Cheers,
 
Kwong
Oorang
07-17-2008, 11:09 AM
Sub Example()
    InsertPicture Worksheets("Sheet1").range("b7"), "C:\Mypath\Oorang.gif"
End Sub
Private Sub InsertPicture(anchorRange As Excel.range, path As String)
    Dim wb As Excel.Workbook
    Dim ws As Excel.Worksheet
    Set ws = anchorRange.Parent
    Set wb = ws.Parent
    wb.Activate
    ws.Activate
    anchorRange.Activate
    ws.Pictures.Insert path
End Sub
lenze
07-17-2008, 03:34 PM
Just an idle thought, but why not place the relative picture in a cell comment for the appropriate cell?
 
lenze
Oorang
07-18-2008, 11:58 AM
Well, largely because AFAIK comments only support text :)
lenze
07-18-2008, 03:49 PM
Well, largely because AFAIK comments only support text :)
 
You can place a picture in a cell comment. It's really quite easy!!
A Google seach will show you how.
 
But, in 2003
1. Insert Comment
2. Choose Edit Comment
3. Right Click Comment and choose Format Comment
4. On the Color and Lines tab of the dialog, under Fill, choose "Fill Effects"
5. Select the Picture Tab and select a picture.
6. Exit Out
 
lenze
Oorang
07-19-2008, 08:45 AM
Oh Yah! I totally forgot about that one. I saw it a few years ago and thought "gee that's slick", then never used it.
 
Sub ExampleWithObjects()
    Dim ws As Excel.Worksheet
    Dim rng As Excel.Range
    Dim cmnt As Excel.Comment
    Dim shp As Excel.Shape
    Set rng = Selection
    Set ws = rng.Parent
    Set cmnt = rng.AddComment
    Set shp = cmnt.Shape
    shp.Fill.UserPicture "C:\EmployeeAvatars\Oorang.gif"
End Sub
Sub ShortExample()
    Selection.AddComment.Shape.Fill.UserPicture "C:\EmployeeAvatars\Oorang.gif"
End Sub
Kwong
07-21-2008, 02:32 AM
Can I also set the size of the picture, please?
 
Kwong
Oorang
07-21-2008, 11:50 AM
Yes, use the Width & Height properties of the shape object.
Kwong
07-21-2008, 06:28 PM
Is it possible to remove all the old pictures in the existing worksheets?
 
Thanks,
 
Kwong
Kwong
07-22-2008, 01:46 AM
Here's the code so far I made:
 
Sub Example()
    Dim Sname As String, Srow As Integer, Scolumn As Integer, Fname As String, Srange As String
    X = (Application.WorksheetFunction.CountA(Sheets("Details").[a:a]))
    For i = 2 To X
        Sname = Sheets("Details").Cells(i, 14)
        Srow = Sheets("Details").Cells(i, 15)
        Scolumn = Sheets("Details").Cells(i, 16)
        Srange = GetXLCol(Scolumn - 1) & CStr(Srow)
        Fname = Sheets("Details").Cells(i, 17) & Sheets("Details").Cells(i, 18)
        Worksheets(Sname).Cells(Srow, Scolumn) = Null
        InsertPicture Worksheets(Sname).Range(Srange), Fname
    Next
End Sub
 
Private Sub InsertPicture(anchorRange As Excel.Range, path As String)
    Dim wb As Excel.Workbook
    Dim ws As Excel.Worksheet
    Dim cmnt As Excel.Comment
    Dim shp As Excel.Shape
    Set ws = anchorRange.Parent
    Set wb = ws.Parent
    Set cmnt = anchorRange.AddComment
    Set shp = cmnt.Shape
    With shp
        .Width = 40
        .Height = 50
    End With
    wb.Activate
    ws.Activate
    anchorRange.Activate
    shp.Fill.UserPicture path
End Sub
 
Private Function GetXLCol(Col As Integer) As String
    ' Col is the present column, not the number of cols
    Const A = 65    'ASCII value for capital A
    Dim iMults As Integer
    Dim sCol As String
    Dim iRemain As Integer
    ' THIS ALGORITHM ONLY WORKS UP TO ZZ. It fails on AAA
    If Col > 701 Then
        GetXLCol = ""
        Exit Function
    End If
    If Col <= 25 Then
        sCol = Chr(A + Col)
    Else
        iRemain = Int((Col / 26)) - 1
        sCol = Chr(A + iRemain) & GetXLCol(Col _
            Mod 26)
    End If
    GetXLCol = sCol
End Function
 
Using comment can adjust the size of the picture, but can I remove the arrow indicator and the shadow? And, how to move the comment?
 
Thanks,
 
Kwong
grichey
07-22-2008, 05:06 AM
movings comments via rec:
 
myComment.ShapeRange.IncrementLeft -500 'where number is direction
Kwong
07-23-2008, 02:18 AM
Thanks, I can move the comment now.
 
But how can i remove the drop shadow of the comment?
 
Also, how can I remove the old comments, because every time when this line runs:
 
Set cmnt = anchorRange.AddComment
 
If there exists previous comment, it returns an error.
 
How can I tackle it?
Oorang
07-23-2008, 06:33 AM
To get rid of preexisting comments, pretest the range. To get rid of the drop shadow, choose a shape that doesn't have one.
Option Explicit
Public Sub Example()
    Dim rng As Excel.Range
    Dim cmnt As Excel.Comment
    Dim shp As Excel.Shape
    Set rng = Excel.ActiveSheet.Range("A1")
    Set cmnt = rng.Comment
    If Not cmnt Is Nothing Then
        cmnt.Delete
    End If
    Set cmnt = rng.AddComment(" ")
    Set shp = cmnt.Shape
    shp.Fill.UserPicture "C:\Test\Oorang.gif"
    shp.Height = 90
    shp.Width = 90
    shp.AutoShapeType = msoShapeRoundedRectangle
End Sub
Kwong
07-23-2008, 07:59 PM
Thanks Aaron,
 
I can get rid of the pre-existing comments now. But the shadow still cannot be removed??? Even I used the rounded rectangle......
 
Kwong
Oorang
07-24-2008, 07:31 AM
Yep you are right. I had tested using a picture with a solid black background and it was blending in with the drop shadow. Getting rid of that drop shadow turned out to be a lot harder than I was expecting. I had to dig into some less documented methods. But here you are:
Edit: Adding missing incrementer.
Edit2: Documented and modularized for addition to knowledge base. Thought I would post preview here.
'-------------------------------------------------------------------------------
' Module       : CommentPictures
' Author       : Aaron Bush
' Date         : 07/24/2008
' Purpose      : Contains procedures related to adding floating picture
'                comments.
' References   : Microsoft Excel XX.0 Object Library (Tested on 2003)
' Dependencies : No dependancies outside module.
' Revisions    : 08/12/2008     Aaron Bush  Added "SendLinkToPictures" sub to
'                                           module. Updated Example sub to
'                                           InsertPicturesub.
'-------------------------------------------------------------------------------
Option Explicit
'Option Private Module
Option Compare Binary
Option Base 0
'Setting this to True will turn off all error handling:
#Const m_blnErrorHandlersOff_c = False
Public Sub InsertPicture()
    '---------------------------------------------------------------------------
    ' Procedure : InsertPicture
    ' Author    : Aaron Bush
    ' Date      : 08/12/2008
    ' Purpose   : Inserts a picture into the selected cell.
    ' Remarks   :
    ' Revisions :
    '---------------------------------------------------------------------------
    Dim strPicPath As String
    'Conditionally Invoke Error Handler:
#If Not m_blnErrorHandlersOff_c Then
    On Error GoTo Err_Hnd
#End If
    strPicPath = Application.GetOpenFilename(Title:="Select Picture:")
    If strPicPath = "False" Then
        Exit Sub
    End If
    If InsertPictureComment(Selection, strPicPath, overWrite:=True) Then
        MsgBox "Picture inserted"
    Else
        MsgBox "Could not insert picture."
    End If
    Exit Sub
    '******* Error Handler *******
Err_Hnd:
    MsgBox Err.Description, vbSystemModal, "Error: " & Err.Number
End Sub
Public Sub SendLinkToPicture()
    '---------------------------------------------------------------------------
    ' Procedure : SendLinkToPictures
    ' Author    : Aaron Bush
    ' Date      : 08/12/2008
    ' Purpose   : Loops through all selected cells and if a hyperlink is found
    '             it attempts to put the link into a comment/picuture.
    ' Remarks   :
    ' Revisions :
    '---------------------------------------------------------------------------
    Dim rng As Excel.Range
    Dim cll As Excel.Range
    'Conditionally Invoke Error Handler:
#If Not m_blnErrorHandlersOff_c Then
    On Error GoTo Err_Hnd
#End If
    InterfaceOff
    Set rng = Selection
    Set rng = Intersect(rng, rng.parent.UsedRange)
    If Not rng Is Nothing Then
        For Each cll In rng.Cells
            If cll.Hyperlinks.Count Then
                InsertPictureComment cll, cll.Hyperlinks(1).Address, overWrite:=True
            End If
        Next
    End If
    '******* Exit Procedure *******
Exit_Proc:
    'Supress Error Handling to Prevent Error-Loops:
    On Error Resume Next
    'Release Objects:
    Set rng = Nothing
    Set cll = Nothing
    'Restore Interface
    InterfaceOn
    Exit Sub
    '******* Error Handler *******
Err_Hnd:
    MsgBox Err.Description, vbSystemModal, "Error: " & Err.Number
    Resume Exit_Proc
End Sub
Public Function InsertPictureComment( _
       ByRef anchorRange As Excel.Range, _
       ByVal imagePath As String, _
       Optional ByVal imageHeight As Long = 90, _
       Optional ByVal imageWidth As Long = 90, _
       Optional ByVal overWrite As Boolean = False _
       ) As Boolean
    '---------------------------------------------------------------------------
    ' Procedure : InsertPictureComment
    ' Author    : Aaron Bush
    ' Date      : 07/24/2008
    ' Purpose   : Inserts a picture that floats like a comment.
    ' Input(s)  : anchorRange - The cell that you want to place a comment on.
    '                           If more than one cell is specified, the first
    '                           cell in the range will be used.
    '             imagePath   - The path to the image you want to use.
    '             imageHeight - Optional. Sets the height of the image.
    '             imageWidth  - Optional. Sets the width of the image.
    '             overWrite   - Optional. If a comment already exists in cell
    '                           specified by anchorRange and overWrite is true
    '                           then the comment will be overwritten. Otherwise
    '                           an exception will be thrown.
    ' Output(s) : True if procedure completed correctly. False if error
    '             was encountered.
    ' Remarks   :
    ' Revisions : 08/12/2008    Aaron Bush  Added comment name truncation to
    '                                       prevent error that occurs when names
    '                                       greater than 32 chars are used.
    '---------------------------------------------------------------------------
    Const lngMaxNameLen_c As Long = 32
    Const strSpace_c As String = " "
    Const lngOne_c As Long = 1
    Dim strCmntName As String
    Dim rng As Excel.Range
    Dim cmnt As Excel.Comment
    Dim shp As Excel.Shape
    Dim xltbx As Excel.TextBox
    Dim lngIndx As Long
    Dim blnRtnVal As Boolean
    'Conditionally Invoke Error Handler:
#If Not m_blnErrorHandlersOff_c Then
    On Error GoTo Err_Hnd
#End If
    'Prevents errors caused by multicell references:
    Set rng = anchorRange.Cells(lngOne_c, lngOne_c)
    'If overwrites are allowed check for pre-existing comments:
    Set cmnt = rng.Comment
    If Not cmnt Is Nothing Then
        If overWrite Then
            'If comment found, then delete it:
            cmnt.Delete
        Else
            Err.Raise vbObjectError, Description:="'" & rng.parent.name & "'!" _
                & rng.Address & " already has a comment."
        End If
    End If
    'Cannot create comment with vbnullstring, so use a space:
    Set cmnt = rng.AddComment(strSpace_c)
    'Load picture into comment's shape background:
    Set shp = cmnt.Shape
    shp.Fill.UserPicture imagePath
    'Set size of comment/picture:
    shp.Height = imageHeight
    shp.Width = imageWidth
    'To get a textbox object (needed later) comment must be named. This
    'generates a unique name:
    On Error Resume Next
    Do
        Err.Clear
        'An error will be thrown if you try to use a name greater than 32 chars:
        strCmntName = Left$(lngIndx & imagePath, lngMaxNameLen_c)
        shp.name = strCmntName
        lngIndx = lngIndx + lngOne_c
    Loop Until Not CBool(Err)
#If m_blnErrorHandlersOff_c Then
    On Error GoTo 0
#Else
    On Error GoTo Err_Hnd
#End If
    'Get textbox object using name:
    Set xltbx = GetTextbox(rng.parent, strCmntName)
    'Kill dropshadow:
    xltbx.ShapeRange.Shadow.Visible = False
    'Flag procedure as complete:
    blnRtnVal = True
    '******* Exit Procedure *******
Exit_Proc:
    'Supress Error Handling to Prevent Error-Loops:
    On Error Resume Next
    'Release Objects:
    Set rng = Nothing
    Set cmnt = Nothing
    Set shp = Nothing
    Set xltbx = Nothing
    'Set Return Value:
    InsertPictureComment = blnRtnVal
    Exit Function
    '******* Error Handler *******
Err_Hnd:
    blnRtnVal = False
    MsgBox Err.Description, vbSystemModal, "Error: " & Err.Number
    Resume Exit_Proc
    Resume
End Function
Private Function GetTextbox( _
        ByRef parent As Excel.Worksheet, _
        ByVal name As String _
        ) As Excel.TextBox
    '---------------------------------------------------------------------------
    ' Procedure : GetTextbox
    ' Author    : Aaron Bush
    ' Date      : 07/24/2008
    ' Purpose   : Gets an Excel.Textbox object by name.
    ' Input(s)  : parent - The worksheet that has the Excel.Textbox Object you
    '                      are looking for.
    '             name   - The name of the Excel.Textbox object you are looking
    '                      for.
    ' Output(s) : An Excel.Textbox object.
    ' Remarks   : Not case sensitive. If object not found or error encountered
    '             output is "Nothing".
    ' Revisions :
    '---------------------------------------------------------------------------
    Const lngLwrBnd_c As Long = 1
    Dim xltbx As Excel.TextBox
    Dim strName As String
    Dim lngUprBnd As Long
    Dim lngIndx As Long
    'Conditionally Invoke Error Handler:
#If Not m_blnErrorHandlersOff_c Then
    On Error GoTo Err_Hnd
#End If
    'Force name to lower case for comparison:
    strName = LCase$(name)
    'Stay away from looping using "For Each" as the Excel.Textboxes collection
    'isn't implemented quite right in XL2003:
    lngUprBnd = parent.TextBoxes.Count
    For lngIndx = lngLwrBnd_c To lngUprBnd
        Set xltbx = parent.TextBoxes(lngIndx)
        If LCase$(xltbx.name) = strName Then
            'Found target, exit loop:
            Exit For
        End If
    Next
    If lngIndx > lngUprBnd Then
        Set GetTextbox = Nothing
    End If
    '******* Exit Procedure *******
Exit_Proc:
    'Supress Error Handling to Prevent Error-Loops:
    On Error Resume Next
    'Set Return Value:
    Set GetTextbox = xltbx
    'Release Objects:
    Set xltbx = Nothing
    Exit Function
    '******* Error Handler *******
Err_Hnd:
    Set xltbx = Nothing
    'Fail silently.
    Resume Exit_Proc
End Function
Private Sub InterfaceOff()
    On Error Resume Next
    With Excel.Application
        .EnableCancelKey = xlErrorHandler
        .Cursor = xlWait
        .StatusBar = "Working..."
        .ScreenUpdating = False
        .EnableEvents = False
        .Calculation = xlCalculationManual
    End With
End Sub
Private Sub InterfaceOn()
    On Error Resume Next
    With Excel.Application
        .EnableEvents = True
        .Calculation = xlCalculationAutomatic
        .ScreenUpdating = True
        .Cursor = xlDefault
        .StatusBar = False
        .EnableCancelKey = xlInterrupt
    End With
End Sub
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.