I have an Access table where each item has attached a Visio file (.vsd).
In my Access form, I would like to see the file. I don't care if it is an editable Visio file, a preview or just an image.
I have built a VBA code that let me load the Visio file from a Directory. But I need to load the file from a table.
Here my VBA code.
Private Sub Carica_Dati()
Dim path As String
path = "C:\Users\VisioFlow_001.vsd"
With Me.VisioObject ' name of the OLE Object where I want to put the Visio file
.Class = "Visio.Drawing.11"
.OLETypeAllowed = acOLELinked
.SourceDoc = path ' HERE I WANT TO LOAD THE FILE FROM A TABLE OF THE DB
.Enabled = True
.Locked = False
.Action = acOLECreateLink
.SizeMode = acOLESizeZoom
End With
End Sub
Here a preview of the form.
UPDATE
Here a picture to show how the file is attached to the table.
Since attachment fields in Access aren't very consistent, directly loading them into an OLE object is not an option, unless you're willing to do sophisticated things
Microsofts documentation on attachments can be found here
My observations on attachments: the binary data field contains one of the following:
Some characters I can't identify + the file type + the file data appended to it
Some characters I can't identify + the file type + a compressed version of the file data appended to it
Microsoft, in all it's wisdom, has supplied us with a way to save the original file to the disk, but hasn't supplied us with a way to remove those initial characters and the file type from the actual file data, or an easy way to identify if the file is compressed or not (you can check the file type with the table supplied in the link to check if it should be).
In conclusion, you're probably off best either replacing your attachment field with an OLE object in the database, or writing the attachment files to disk before displaying them.
If you use an OLE object field, and load them in as long binary data (not through the GUI), you can easily achieve the behaviour you seek without writing the file to disk, since the binary data is available without any extra characters.
To write an attachment file to disk:
Dim rsForm As DAO.Recordset2
Dim rsFiles As DAO.Recordset2
Set rsForm = Me.Recordset
Set rsFiles = rsForm.Fields("attachment_column").Value
If Not rsFiles.EOF Then
Dim fileLocation As String
fileLocation = Environ("TEMP") & rsFiles.Fields("FileName").Value
rsFiles.Fields("FileData").SaveToFile fileLocation
'Your existing code to display the OLE object here
End If
You do not want to use the Attachment feature. Its purpose is different than what you are attempting.
Put the images into their own stand alone folder outside of the database.
In the table that holds the records for your main form - you need a new field which holds the path & image file name. This is a text field. (If the path segment is uniform for all one can insert that elsewhere via code rather than store it in this field.)
Then in form design - use the image control. This control (all controls) have a source property - that will change with each record using that field that holds the path & file name.
Do a bing/google on the topic of changing an image with every record - the set up isn't intuitive necessarily. Note that older editions did things differently so be sure you get relatively recent advice.
Then when you are using the form and change records - the image will change.
Note after having typed all this.... I have no idea if the visio file type works - I know that jpg and bmp do... so first sanity check a simple fixed image with that file type to see if it works ...
Related
I have a table with a field that is of type OLE Object. I then have a form with a number of fields. Some are just text fields. But, I also have an Image object on the form. When a user clicks a button, a dialog opens and they can pic a photo. Once they select the photo, the Image object displays that picture. I want to save that image to database. What I have only seems to save a reference to where the file is located, on the computer. So, this would not work if the db is moved. Here is the code I have:
Dim wrkCurrent As DAO.Workspace
Dim dbs As DAO.Database
Dim rstPerson As DAO.Recordset
Set wrkCurrent = DBEngine.Workspaces(0)
Set dbs = CurrentDb
Set rstPerson = dbs.OpenRecordset("SELECT * FROM tbl_person WHERE id =" & ID)
With rstPerson
.Edit
!bio_photo = Me.Image37.picture
.Update
End With
How would I save the image file to the OLE Field, so that I could load it back to the Image object, on the form, at a later time?
Thanks
Answer:
So, what I ended up doing was following this https://support.microsoft.com/en-us/kb/210486 [EDIT: that link is now dead, try this instead]
I use the readBLOB function to read the file and save it into the database. Then, when I run a report or open a form that has the picture, onload, I use the WriteBlob function to write the file to a temp folder and then use that path to populate an Image object.
Databases can grow to enormous sizes when you start embedding images, leading to slower queries, crashes, timeouts, and dissatisfied users. Use OLE with caution when adding images into a database
Simple Google search has how to load ole object from folder into table
And a search on this site comes up with auto attach images using vba
I'm playing around with splitting access databases. It appears that each table contains a hard link to the backend file in the linked table manager.
But if I wanted to send the file pair to someone through email to look at, the hard links will break. Right now we're at separate offices just testing changes to the program. This isn't in production. I don't want them to get into the development mode and edit the linked table manager because it would be too hard.
Is there a way to tell access to simply look in the front end file's directory for the backend file? Is there a way to force a prompt on the front end to let them choose the location of the backend file?
Thanks!
The simple solution is to on startup check if the table link(s) point to the current directory, and if not, then you run re-link code. That way the pair of files will work if you move the pair to a different folder or re-name the folder.
The above is a common setup and EVEN recommend for single user applications that SHOULD be split and benefit by being split.
So on startup, check the path of a linked table. I use the following code to return the path of currently linked tables.
Function strBackEndPath() As String
' returns the path name to the back end
' and includes tralinig \
Dim mytables As TableDef
Dim strTempBack As String
Dim strFullPath As String
strFullPath = ""
For Each mytables In CurrentDb.TableDefs
If Left(mytables.Connect, 10) = ";DATABASE=" Then
strFullPath = Mid(mytables.Connect, 11)
Exit For
End If
Next mytables
strBackEndPath = Left(strFullPath, InStrRev(strFullPath, "\"))
End Function
With above, then on startup I can go:
If CurrentProject.path & "\" <> strBackEndPath Then
' call re-link code
End If
And there are TONS of re-link code examples floating around but here is a link to some re-linking code.
http://access.mvps.org/access/tables/tbl0009.htm
Thus if the links don’t point to the back end database in the same folder, then re-linking will ONLY occur once and after that only the above “test” to ensure that front end and back end are are linked.
If the folder is renamed or as noted a user moves the files to a different location then again the re-link will occur.
Right-click on the front-end tables and select Linked Table Manager. From there, you can browse for the location of the back-end tables
I have written a simple web service that returns large volumes of csv data. I will to import this into Excel in a tabular format using Excel's "Data From Web" function.
Is there a way to get Excel to automatically parse the csv fields returned into individual columns as part of the import operation?
At present the only means I have for doing this is to first import the data into a single column and then write VBA code to select the data and split it using TextToColumns. This feels messy / error-prone.
The other alternative I have is to modify the web server to serve back the data as HTML. However, I'm reluctant to do this as adding tags around each csv field will greatly impact the volume of data returned.
Adamski,
Here is something that I use. I found the core somewhere on the internet, but don't know where.
What it does is it opens a tab separated file and reads the data in an excel sheet
If Answer1 = vbYes Then 'I asked prior if to import a tab separated file
Sheets("ZHRNL111").Select 'Select the sheet to dump the data
On Error Resume Next
With ActiveSheet
If .AutoFilterMode Then .ShowAllData 'undo any autofilters
End With
Sheets("ZHRNL111").Cells.Clear 'remove any previous data
On Error GoTo 0
Range("A1").CurrentRegion.Delete
Fname = MyPath & "\LatestReports\Report-111.tsv"
Open Fname For Input As #1
iRow = 1
Line Input #1, Record
On Error Resume Next
Do Until EOF(1)
P = Split(Record, vbTab)
For iCol = 1 To 14
Cells(iRow, iCol) = P(iCol - 1)
Next iCol
iRow = iRow + 1
Line Input #1, Record
Loop
On Error GoTo 0
Close 1
End If
Regards,
Robert Ilbrink
Depending on the version of excel you are running you should be able to open the .csv in excel and use the text to columns feature built into excel.
Also, if you could modify your csv to split columns based on commas "," instead of tabs excel would open it directly without the need to format it.
I know however this can sometimes be a problem depending on the data you are importing because if the data contains a comma it must be inside quotations.
In my experience the best way is to use quotations on every field if possible.
Hope this helps.
I am actually creating a product right now to do this in both XML and JSON for Excel. I know comma delimited does work in Excel, with some caveats. One way around it is to put some "" around the text in between the delimiters for the "Data From Web" feature. There are still issues with that however. I did find that despite it's increased size, XML was the best option for quick turn around. I was able to create the service and hand my project manager the Excel document which he could update at anytime.
Ive just inherited an MS Access 2003 system and need a bit of VBA to put behind a command button to open MyComputer at a specific folder to view the files there.
The folder name will come from a field on a form.
I did have
Application.FollowHyperLink "C:\" & Me![ref] (ref is in the format abcd-1234)
when its hard-coded it works fine, but i cant seem to get it to open when picking the foldername up from the form.
any hints? (other than binning access!)
thanks
See what the text looks like as you're submitting it to FollowHyperlink. You can insert a line like this in your code:
MsgBox "C:\" & Me![ref]
Perhaps it's not what you expect. It's always good to check.
What happens when it doesn't work. Do you see any error messages or any other symptoms which could help us nail this down?
My first thought was spaces in a folder name might create problems. But I don't think that's the answer because FollowHyperlink works fine for me in this example:
Application.FollowHyperlink "C:\Access\spaces in name\"
So the best I can offer is to see what you're asking FollowHyperlink to use. If that effort doesn't lead you to the answer, add a specific example which fails to your question.
This code always work for me:
Dim filePath = <"Insert the path of the directory to open inside of opening and closing parenthesis">
Application.FollowHyperlink filePath, vbNormalFocus
Normally, I store a few directories in a table inside the DBMS, which helps when linking hundreds of images to a database instead of embedding. For instance, I have a table called, "dbLocations." Inside this table, there are only two fields: 1) picLocation 2) Description.
The field picLocation has the value of the network path, i.e, C:\My Documents or G:\Whatever Directory or \\groups1\for UNC paths.
The field Description is what it implies, a description of the picLocation.
I use tables to store directory locations because they linking to files (.jpg, .png) stored on a network drive. As time evolves, directories can get changed (I move a folder to another location, or if the UNC changes, etc.).
If you hard code the location(s) over several subs or modules, you will need to change each one; which is very inefficient. So, in order to save time and a lot of headaches, I use the Domain Lookup function which allows me to only change the file location just once and in an easy to find place, namely, the dbLocations table.
In essence, I am looking up the value of the location inside the table where the picLocation matches the description of, Alert Pics. (I am creating a database that will be used to track Trespassers and other vagrant persons for work)
Dim filePath as String
filePath = DLookup("picLocation", "dbLocations", "[Description] = 'Alert Pics'")
Application.FollowHyperlink filePath, vbNormalFocus
With these three lines of simple code, you can navigate to a specific directory.
I have a table in an access table which contains Product entries, one of the columns has a jpg image stored as an OLE Object. I am trying to import this table to MySQL but nothing seems to work. I have tried the MySQL migration tool but that has a known issue with Access and OLE Objects. (The issue being it doesnt work and leaves the fields blank) I also tried the suggestion on this site
and while the data is imported it seems as though the image is getting corrupted in the transfer. When i try to preview the image i just get a binary view, if i save it on disk as a jpg image and try to open it i get an error stating the image is corrupt.
The images in Access are fine and can be previewed. Access is storing the data as an OLE Object and when i import it to MySql it is saved in a MediumBlob field.
Has anyone had this issue before and how did they resolve it ?
Ok so in the interests of airing my dirty code in public here what i came up with.
Note : this is a hack designed to be used once and then thrown away.
This Method takes in a datarowview containing 1 row of data from the access table. The Images are wrapped in OLE serialization, im not entirely familiar with how this works but its how Microsoft apps allow any object to be embedded into something else. (eg images into Excel Cells). I needed to remove the serialization junk around the image so i loaded the entire field as a Byte array and searched through it for 3 concurrent entries (FF D8 FF) which represent the beginning of the image data within the field.
Private Function GetImageFromRow(ByRef row As DataRowView, ByVal columnName As String) As Bitmap
Dim oImage As Bitmap = New Bitmap("c:\default.jpg")
Try
If Not IsDBNull(row(columnName)) Then
If row(columnName) IsNot Nothing Then
Dim mStream As New System.IO.MemoryStream(CType(row(columnName), Byte()))
If mStream.Length > 0 Then
Dim b(Convert.ToInt32(mStream.Length - 1)) As Byte
mStream.Read(b, 0, Convert.ToInt32(mStream.Length - 1))
Dim position As Integer = 0
For index As Integer = 0 To b.Length - 3
If b(index) = &HFF And b(index + 1) = &HD8 And b(index + 2) = &HFF Then
position = index
Exit For
End If
Next
If position > 0 Then
Dim jpgStream As New System.IO.MemoryStream(b, position, b.Length - position)
oImage = New Bitmap(jpgStream)
End If
End If
End If
End If
Catch ex As Exception
Throw New ApplicationException(ex.Message, ex)
End Try
Return oImage
End Function
Then its a matter of pulling out this data into a bitmap. So for each row in the access table i extract the bitmap and then update the corresponding MySQL entry.
It worked fine but im guessing i could have removed the serialisation stuff in a better way, perhaps theres an API to do it.
As far as I remember, the Microsoft "SQL Server Migration Assistant for Access" will properly migrate OLE Images, but this is only for Access->SQLServer. However, what you can do is use this to migrate to SQLServer Express (free download) and then migrate from SQLServer to MySQL.
There's also olefield - Python module to extract data out of OLE object fields in Access. I successfully extracted BMP files with it. It could probably work with jpeg images, but I haven't tried it.