Need to Display a Corresponding Image For Each Record

Hello. I am trying to learn how to use LibreOffice 7.5 (64k) on a Windows 10 Desktop.
.
There are 1,200 records in my database.
When in Form-View, I want to see a corresponding picture that is unique for each record.
.
HOW I DID THIS IN ACCESS:
In my old Access database, I did not EMBED the image in Access because the very large file-sizes from that many pictures crashed the database. INSTEAD, I used an Image-Frame Control that merely referenced the filename path that was stored in a separate text control. So the form temporarily loaded the picture when that record was displayed in the form… nothing was stored.

To make this work in my Access database, I inserted the following code behind the Form:
.
Function setImagePath()
Dim strImagePath As String
On Error Goto PictureNotAvailable
strImagePath = Me.txtImagePath
Me.ImageFrame.Picture = strImagePath
Exit Function
PictureNotAvailable:
strImagePath = “C:\Windows…(insert path)…\NoPicture.jpg”
Me.ImageFrame.Picture = strImagePath
End Function
.
Then I modified the Form’s Properties (OnCurrent and AfterUpdate) to: =setImagePath().
.
.
WHAT I’VE DONE IN LIBREOFFICE BASE SO FAR:
I do not know how to do the above in Base… but I did find the “Image Control” on the Form’s Toolbar, and figured out how to add the image by double-clicking on it and selecting the picture.

But before I add too many pictures to this database, I need to know whether this method actually EMBEDS the image… or just references the pathway? Based on what I saw in a tutorial, I suspect that this method embeds the picture and will eventually cause my database to crash and become unwieldy.

Therefore, is this the most-efficient way to display a corresponding picture for each record in a form in a large database… or is there a much better method that merely references the pathway?

THANK YOU!

Perhaps Store base images external (not in database) might help you.

1 Like

This looks like what I want… but I know very little about Base and still have some questions.
.
Is the “Form Control” that is referenced in the Solution you linked the SAME as the “Image Control” that is located in my Form Control Toolbar?
.
If so, WHERE do I link the “Image Control” to the text field that contains the path? Under the “Data” tab for the Image Control, I tried selecting the text field (fldImagePath)… but that doesn’t work.
.

Thanks!

Chapter 8 of the Base Guide has information on handling embedded and linked images.

I am not what you might call an experienced user of Base so I can’t give in-depth information.

1 Like

If you bind an Image-Control to a VARCHAR with size 256 there is not much possibility to store your images.
.
I always store filenames or paths. You may need to provide an URL to the file.

Do not understand this. I have found 200 more than enough in my dealings. It is just storing the URL:

@DMG
You have not stated (in multiple questions) what database you are using. This is always important and one can only guess it is HSQLDB embedded.
.
Also:

.
was this a new table or an existing one and were there records in there already? Field type defined?

Yes. Chapter 8 was very helpful.

Sorry, Ratslinger… I forgot to say that I am using HSQLDB embedded.
.
The table was pre-existing from an Access import, which required VB code to display dynamic pictures from a file path. I was hoping the code would also import into Base (since I had NO IDEA where to find the code in Base! lol)
.
But, I discovered today, that the underlying code/macro was not even there, and that is why it wasn’t working.
.
Because I am such a complete Newbie to LibreOffice Base, I found the following step-by-step video and information to be extremely helpful. I was able to make it work, so I consider it a SOLUTION. :slightly_smiling_face:
.

.
THANK YOU, EVERYONE! Base has been very challenging for me… but I’m going to love cutting ties with Microsoft products.

They are enough to store the path, but there was the original concern by @DMG not to embed the image:

And 200 or 256 bytes would give quite tiny embedded pictures.

OP never stated what field types were used at any time.

Hi, Wanderer and Ratslinger.
.
With regard to field types… The table field types that eventually worked for me were:
.
• fldImagePath (type: Text [VarChar]) – Contains the image filename.
• My table also contained a unique autonumbering ID field (Integer type).
.
On my form, I used the “Image Controller” option on the Form Control toolbar, and named it “ctrlPictures”
.
Another requirement (of the referenced video tutorial) is that the images be located inside a folder named “images,” which is located inside the same folder as the database.

@DMG
In my sample (used for provided image) van be but there is no specific folder for the images. Having the odb and a folder for images in a specific folder allows for portability but it is not necessary.
.
The only reason field types came up was because of the issues you seem to be having. You never mentioned the original field type you used. Based upon the field type used determines if you stare an image or a URL. Already showed Varchar type for URL so here is the other:
.
Screenshot at 2023-03-04 18-26-12

Thank you so much for your help, Ratslinger! I didn’t want to bloat the database, so I used the method that stored only text (not an image). But I wasn’t able to make it work until I added the code module discussed in the tutorial video… now it works!

?? shouldn’t be any code necessary. I did not look at the video as I really don’t think much of any of them but I see no reason for code of any type.

Hmmm… Well, perhaps I missed a step when I was first trying to do it without the code. I’m “flying by the seat of my pants” as I don’t have much experience with this, so it wouldn’t be unusual for me to screw it up. lol
.
If you want to see the code and its 6 functions, I have copied it below. Mr. Johnson said he wrote it after reading a book he found to be very helpful: “Database Programming with OpenOffice.org Base and Basic.”

OPTION EXPLICIT

' When the record is changed on  the form various events are fired, this routine
' is designed to capture the "After Record Changed" event. Information pertaining 
' to this event is captured in the event object e below.
' We use the custom function that I wrote "getFormFromEvent" to get a reference to the
' form which also acts as a datasource (object the contains the records, Microsoft would 
' call this a recordset). 
' From the form/Recordset dsVideos we can get a reference to the Image Control

Sub AfterRecord_Change(byref e as Object)
	Dim dsVideos as Object
	Dim oImageControl as Object
	Dim oGraphic as Object
	dim szFullImagePath as String, szFile as String 
	
	' Get reference to the form that threw this event
	dsVideos = getFormFromEvent(e)		' Get Reference to form / resultset
	
	oImageControl = dsVideos.getByName("ctrlPictures")	' Get Reference to Image Control
	szFile = getColumnValue(dsVideos, "fldImagePath")		' Get value from VideoID field
	szFullImagePath = getDbPath() & "RecipePictures/" & szFile     'This is the name of the folder where pictures reside.
	
	if imageFileMissing(szFullImagePath, oImageControl) then Exit Sub

	oGraphic = createGraphic(szFullImagePath)
	oImageControl.Graphic = oGraphic
	oImageControl.ScaleImage = true

End Sub


Private Function imageFileMissing(byval szPath as String, byref oImageControl as Object) as Boolean
	Dim szTest as String
	' Exit the code if no image file present
	szTest = Dir(szPath, 0)
	If szTest = "" Then
	  oImageControl.Graphic = Nothing	
	  Exit Function
	End If 
End Function

' This function returns the Path (as a URL, which is best for LibreOffice as this handles cross platform issues best)
' meaning if you put other files in subdirectory of database file will always be in the correct place
Function getDbPath() as String
	Dim szPathFile as String
    Dim oDoc as Object
    Dim lErr as Long
    Dim szModuleRoutineName as String
    
    szModuleRoutineName = "m_frmReviewBigPicture.getDbPath"
   	
	On Error Resume Next
	szPathFile = ThisComponent.getURL()
	If err <> 0  Or szPathFile = "" Then
		On Error Resume Next
		szPathFile = ThisComponent.Parent.getURL()
		if err <> 0  Or szPathFile = "" Then
			lErr = err
			On Error Goto ErrorCheck	' Reset Error Handling
			error(err)	' Throw Error
			Exit Function
		End if
	End if
	On Error Goto ErrorCheck	' Reset Error Handling
	
	'szPathFile = mid(szPathFile, 8)		' Remove file:// from start of string
	getDbPath = removeFileNameFromPath(szPathFile)
  Exit Function

  ErrorCheck:
    MsgBox "Error in " & szModuleRoutineName & chr(13) & "Error Number: " & err & " " & Error$ & chr(13) & "Error Line : " & erl  	
    error(err)	' Throw unresolved error up the stack
End Function


Function createGraphic(byval szFilePath as String) as  Object
	Dim oSFA as Object	' SFA is Simple File Access
	Dim oInputStream as Object
	Dim arrArgs(0) as New com.sun.star.beans.PropertyValue
	Dim vGraphicProvider as Variant
	Dim szURL as String
	
	oSFA = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")
	szURL = ConvertToURL(szFilePath)		' Built in Basic Function
	
	oInputStream = oSFA.openFileRead(szURL)
	arrArgs(0).Name = "InputStream"
	arrArgs(0).Value = oInputStream
	vGraphicProvider = CreateUnoService("com.sun.star.graphic.GraphicProvider")
	createGraphic = vGraphicProvider.queryGraphic(arrArgs)
End Function


Function getFormFromEvent(e as Object) as Object
    Dim szModuleRoutineName as String
    szModuleRoutineName = "m_frmReviewBigPicture..GetFormFromEvent"
    On Error Goto ErrorCheck

    select case e.Source.ImplementationName
    case "com.sun.star.form.FmXFormController"
        GetFormFromEvent = e.source.model
    case "com.sun.star.form.OButtonControl"
        GetFormFromEvent = e.source.model.parent
    case "com.sun.star.comp.forms.ODatabaseForm"
        GetFormFromEvent = e.source
    case else
        msgbox e.Source.ImplementationName
        msgbox "Unknown event in mSwitchboard.LoadMainKeywordFile"
        msgbox "Need to look at the locals window to trace up the stack" & chr(13) & "to find the form reference."
    end select
    Exit Function

  ErrorCheck:
    MsgBox "Error in " & szModuleRoutineName & chr(13) & "Error Number: " & err & " " & Error$ & chr(13) & "Error Line : " & erl
End Function



' This is just a wrapper function to  make calling getColumnData (below) simpler
Private Function getColumnValue(byref ds as Object, byval szColumnName as String) as Variant
		getColumnValue = getColumnData(ds.Columns.getByName(szColumnName))
End Function

Private function getColumnData(oCol) as variant
    ' Do not return Error code from this function
    ' do checks in calling function
    Dim vOut as variant
    select case oCol.TypeName
        case "INTEGER": vOut=oCol.Int
        case "INT"  : vOut=oCol.Int
        case "LONG": vOut=oCol.Long
        case "VARCHAR": vOut=oCol.String
        case "DOUBLE": vOut=oCol.Double
        case "BOOLEAN": vOut=oCol.Boolean
        case "DECIMAL": vOut=oCol.Double
        case "NULL": vOut=oCol.Null
        case "SHORT": vOut=oCol.Short
        case "ARRAY": vOut=oCol.Array
        case "BLOB": vOut=oCol.Blob
        case "BYTE": vOut=oCol.Byte
        case "BYTES": vOut=oCol.Bytes
        case "CLOB": vOut=oCol.Clob
        case "DATE": vOut=oCol.Date
        case "OBJECT": vOut=oCol.Object
        case "REF": vOut=oCol.Ref
        case "TIME": vOut=oCol.Time
        case "TIMESTAMP": vOut=oCol.TimeStamp
        case else: vOut=oCol.String
	End Select
		getColumnData = vOut
End Function



Function removeFileNameFromPath(byval szPath as string)
    Dim i as integer, iLen as Integer, iPos as integer
    Dim szModuleRoutineName as String
    szModuleRoutineName = "mSharedFunctions.removeFileNameFromPath"
    On Error Goto ErrorCheck
    
    iLen = len(szPath)

    for i = iLen to 1 Step -1
        select case mid(szPath, i, 1)
        case "/","\"
            iPos = i
            exit for
        end select
    next
    if iPos > 0 Then
        removeFileNameFromPath = left(szPath,ipos)
    else
        removeFileNameFromPath = "[Not a Path]"
    end if
  Exit Function

	ErrorCheck:
    MsgBox "Error in " & szModuleRoutineName & chr(13) & "Error Number: " & err & " " & Error$ & chr(13) & "Error Line : " & erl    
End Function

You were provided with a link to a sample early on here and here is a post I did years ago:
.

.
No code needed.

1 Like

@Ratslinger I went back and tried it again… and this time it worked. I’m not sure why it didn’t work the first time, but you are right… no code involved and this is a much easier method.

Thanks so much for your help!