I created a MS Access (2003) table, using VB6. Naturally, even though VB6 on the surface works strictly with ANSI character set, under the hood, strings are internally correctly stored in fully UNICODE. The proof is the fact that when I write my data, containing diacritic characters to MS Access, database its flawless.
I want to underline that the date in my MS Access 2003 contains a field that is "Directory+Filenames (full path)" pointing to files on my HDD with diacritic characters.
Great, so far so good. Now for the problem!
When I turn back and read those records containing diacritic characters from MS Access 2003 and feed the "Directory+Filenames (full path)" to say, VLC Media Player, it does not find it, because VB6 internally striped diacritic signs.
Is this such rare case? No similar cases found on the web.
Thanks to an unknown soul.
EDIT More info from the question asker.
above all thanks. Yes, I'm using VB6 (classic); an old timer, but for fun. Here's a subroutine that tries to invoke VLC.
Private Sub GoPlay(**FileToPlay** As String)
Const vlc_exe = "C:\Program Files\VideoLAN\VLC\vlc.exe "
FileToPlay = vlc_exe + """" + **FileToPlay** + """"
Me.Enabled = False ' Block any futher action on the Form before the current film showing doesn't end
'=================
' Go play video
'=================
StartVLC_common FileToPlay ' Go play video
Me.Enabled = True
Me.ZOrder
End Sub
As you see I pass the argument as String. That may be the problem!
This is how "StartVLC_common" is defined:
Public Function StartVLC_common(VideoToShow As String)
'===================================== ' Start a process, in this case VLC
'=====================================
On Error Resume Next
StopVLC_common ' Avoid multiple brands playing, so kill any previous instance
'=====================================
' Start the process.
VideoToShow = Trim$(VideoToShow)
If VideoToShow = "" Then
Exit Function
End If
glPid = Shell(VideoToShow, vbNormalFocus)
If glPid = 0 Then
MsgBox "Could not start process", vbExclamation, "Error"
End If
End Function
Good news! Thanks to different people suggestions, I did some brainstorming and came to the conclusion. Before I was passing VB string to subroutine "GoPlay" containing file name to play. Now I pass ADO recordset field read directly from MS Access table that contains the file name to play.
Thanks to all.
Related
We've recently upgraded some PCs and have subsequently come across some issues with the VBA code in an Access frontend we use to perform operations on a MySQL database. The specific piece of code pulls a serial number from the database and then prints it to a Dymo Labelwriter 450 as a barcode.
Style = vbExclamation + vbYesNo
Title = "Print Label For " & Me.txt_Barcode & " ?"
Response = MsgBox("Do you want to print a label for serial number " & Me.txt_Barcode, Style, Title)
If Response = vbYes Then
Dim myDymo As Object
Dim myLabel As Object
'On Error Resume Next
Set myDymo = CreateObject("Dymo.DymoAddIn") '
Set myLabel = CreateObject("Dymo.DymoLabels")
If (myDymo Is Nothing) Or (myLabel Is Nothing) Then
MsgBox "Unable to create OLE objects"
Exit Sub
End If
The code now breaks at line 8, i.e.
Set myDymo = CreateObject("Dymo.DymoAddIn") '
The error code I was getting was relating to ActiveX (which seemed possible that it might relate to going from 32-bit to 64-bit), but since installing the latest DLS from Dymo (DLS8Setup.8.2.2.996), it seems to have evolved to the following:
Run-time error '-2147467261 (80004003)
Automation error
Invalid pointer
I'm hoping someone can point me to an easy fix so I don't have to totally re-write the code!
Thanks in advance!
I managed to resolve this one in a couple of steps and to be honest, I'm not sure which exactly fixed this specific part of the problem:
First was to run the DYMO_Label_v.8_SDK_Installer
I also switched from the latest Dymo Connect to DYMO Label v.8
I then had to ensure the Barcode font we're using was installed as an admin for all users, rather than just a specific user profile
and finally, and I think this may have been the kicker, the software was looking for a label template called 'Serial.label' which I found on our server and copied and pasted into the C: drive where the software was looking for it.
I'm just glad I didn't have to re-write the code!
I needed to copy some values from MS Access table into Excel using VBA code. I had done this many times and considered myself experienced. In my code I export the data using the following statements:
sh.range("A" & row).Value = rs("MyField")
where sh is Excel sheet, row is integer (long) and rs is recordset (either DAO or ADO, without any effect on the problem under consideration).
My code worked well on my computer with installed MS Office 2007. But when my client ran the code on his machine with MS Office 2010, it failed and kept failing very randomly. E.g. when debugging VBA in MS Access module step by step by pressing F8 it always worked. But when I pressed 'run' F5, it failed very soon.
After many trials and errors (I tried to open the recordset using different options and recordset types and caching the records etc.), I finally found that if I write
sh.range("A" & row).Value = rs("MyField").Value
everything works just fine. But according to the docs (e.g. http://msdn.microsoft.com/en-us/library/office/ff197799(v=office.15).aspx ) the Value property is the default property of the field object, which in turn is the default collection of the recordset object.
But it seems that I cannot rely on the defaultness, which I have been doing in most of my code. Actually I found a solution to my problem, but I still have no idea about the cause. Does anyone know why is the code doing this? What is the problem?
PS: I also found that if I expand the one-line statement into two lines (three with declaration):
dim v as Variant
v = rs("MyField")
sh.range("A" & row).Value = v
it also works...
Since rs("MyField") is a Field object, if you do ...
MsgBox TypeName(rs("MyField"))
... Access will tell you its type is Field.
So TypeName() is one example where the object itself is referenced directly instead of its default .Value property.
But something like Debug.Print always references .Value, so Debug.Print rs("MyField") is the same as Debug.Print rs("MyField").Value
If you know exactly when .Value will be referenced implicitly and when it will not, you can add it only when absolutely required and omit it the rest of the time.
However, some Access developers recommend always including .Value to avoid such confusion. If that seems like too much effort to you, at least consider including .Value when you do any assignment ...
something = rs("MyField").Value
... and be watchful for any other contexts where you don't get what you want without .Value
In a data validation form, I have a subroutine checking previously-entered data on a LostFocus event by ensuring that the release time (TimeReleased in table; Me.txtTimeReleased on form) is after the capture time (ObservationTime in table; Me.txtObservationTime on form). I'm using LostFocus rather than BeforeUpdate because the data were bulk-imported into the db and are now being error-checked.
My users keep getting a compile error (Compile Error: method or data member not found) upon tabbing out of the field this sub is attached to but I cannot reproduce the problem locally. The error occurs on this line:
If (Me.txtTimeReleased) <= (Me.ObservationTime) Then
and the part highlighted is '.txtTimeReleased'
Full code block:
Private Sub txtTimeReleased_LostFocus()
Dim badData As Variant
Dim resp As Variant
'Also check that time released is after time captured
If Not IsNull(Me.txtObservationTime) And Not IsNull(Me.txtTimeReleased) Then
If (Me.txtTimeReleased) <= (Me.ObservationTime) Then
resp = MsgBox("Release time must be after capture time." & vbCrLf & "Please double check this field's value: is it correct?", _
vbYesNo + vbExclamation + vbDefaultButton2, "Release Time Before Capture Time")
If resp <> vbYes Then badData = True
End If
End If
If badData = True Then
Me.cmbTaxonId.SetFocus 'set focus away so can set focus back
With Me.txtTimeReleased
.SetFocus
.SelStart = 0
.SelLength = 10
End With
End If
End Sub
Other things to note:
Both the table field and form control are formatted as 'Short Time' (24-hour time)
There is an input mask on that form control for 24-hour time; I use input masks very rarely and thus aren't familiar with them--perhaps the input mask could be causing the problem?
There are similar LostFocus subs on most of the other controls which do not produce this (or any other) error
Things I've tried:
Checking spelling
Fully decompling and recompiling the code: starting with shift, compact and repair with shift, open with /decompile flag while holding shift, compact and repair with shift, re-open with shift, and finally compile (without error)
Replacing the form in their database with one that works fine for me on the same data
Google
Things that seem odd to me:
I can't reproduce the error locally.
The error is triggering on the second instance of
Me.txtTimeReleased rather than the first: it has already passed a Not
IsNull(Me.txtTimeReleased) check.
The fact that it's a compile error: could that be masking something else?
Thanks for your time, and please let me know if there's any additional information that would be useful. Any thoughts are most welcome!
You checked for Null txtObservationTime and txtTimeReleased, but compare then txtTimeReleased and ObservationTime. Maybe solution is:
If Not IsNull(Me.txtObservationTime) And Not IsNull(Me.txtTimeReleased) Then
If (Me.txtTimeReleased) <= (Me.txtObservationTime) Then
Opening the .mdb with the /decompile flag is one of the first things I would have suggested, but you said you already tried that.
Here's another undocumented trick to deal with "hidden" compile problems that get baked in by VBA behind the scenes:
First, make a backup copy of your .mdb just to be safe (this is, after all, an undocumented technique).
Then, save your form to a text file using SaveAsText:
SaveAsText acForm, "MyFormName", "C:\MyFormName.txt"
Finally, re-load your form using the equally undocumented LoadFromText:
LoadFromText acForm, "MyFormName", "C:\MyFormName.txt"
Compile.
Compact.
Repair.
Hope for the best.
Good luck.
I suggest you use variables:
intThat = Me.txtTimeReleased
If intThis <= intThat Then
Try using ! instead of a dot:
intThat = Me!txtTimeReleased
If intThis <= intThat Then
And now, the answer that worked for me last week:
Comment out the offending line.
Run a compile that is successful.
Restore the offending line.
The compile may work now. Don't ask me why.
I just started a job with a new company where previous developers had created many automated tasks. Of course, there is virtually no documentation and I didn't have a chance to work with the previous developer so now I'm trying to sift through all these processes looking for one that modifies some specific files.
I've scripted all the stored procs in SQL and used a search tool and didn't find what I was looking for, so now I am wondering if the process I need is located in one of many Access databases that are used. With SQL Server, it was easy to write a C# app to script the procs so I could search through them, but with Access it looks like I'm confined to opening each db individually to search through the code files.
Is there any way to programatically search through VBA code files?
If your interest is searching code modules in an Access database file, you can use the VBE object model. This sample searches for a word in all the modules of the ActiveVBProject of the current database. If the database includes more than one VBProject, you can enumerate the VBProjects collection and search the projects one at a time by name:
For Each objComponent In Application.VBE.VBProjects(ProjName).VBComponents
Or if you prefer to reference the project by number rather than name, just be aware the numbering starts with 1 rather than 0.
Public Sub findWordInModules(ByVal pSearchWord As String)
'Dim objComponent As VBComponent
' VBComponent requires reference to Microsoft Visual Basic
' for Applications Extensibility; use late binding instead:
Dim objComponent As Object
Dim strMessage As String
Dim strModuleList As String
strModuleList = vbNullString
For Each objComponent In Application.VBE.ActiveVBProject.VBComponents
If objComponent.CodeModule.Find(pSearchWord, 1, 1, -1, -1) = True Then
strModuleList = strModuleList & "; " & objComponent.Name
End If
Next objComponent
strMessage = "Text '" & pSearchWord & "' found in "
If Len(strModuleList) > 0 Then
strMessage = strMessage & "modules: " & Mid(strModuleList, 3)
Else
strMessage = strMessage & "no modules"
End If
Debug.Print strMessage
End Sub
Review the Access help topic for that Find method; you may prefer different options than I used.
If you want to target multiple db files and search the modules in each, you could automate this using the OpenDatabase method. I'll leave the details of that part up to you.
Another option, not previously mentioned - is to just print the Project Code, from the context menu, in the VBA Editor. The steps below, can be modified, to suit applications available, but the result is the same - searchable text.
From the VBA Editor, right click the project name, and click print, from the context menu that appears. Make sure "Code" is checked, and click "OK". The printer can be changed, from the "Setup..." menu, available in the last dialog.
On a side note - stand alone modules, SQL, tables, etc, are available for printing, from the "Database Documenter", in the "Analyze" group, of the "DATABASE TOOLS" tab.
Very useful, for sorting and outlining underlying SQL, of Access queries.
Best to download the free MZ-Tools for VBA and use their search/replace function.
Edit
MZ-Tools for VBA is no longer available. The paid version works with newer office installations.
I have a program that uses a Microsoft Access database for its back-end. I need to have some VBA code (that calls a web service) execute whenever specific tables/fields are updated by the program. I see this working just like a trigger in SQL Server.
Is it possible to monitor for and act upon changes like this in Access?
Update
The program in question does not run inside of Access (i.e. not a VBA app), it simply uses an MDB file as its back-end storage. Unfortunately I don't have access to the program's code as it is a closed third party application.
This question is old, but the answers are no longer correct. Access 2010 added data macro events that can be run when data is inserted, updated or deleted. The following events are available while using either the table datasheet view or table design view (events are attached directly to table and not through the form macro button):
After Delete Macro Event
After Insert Macro Event
After Update Macro Event
Before Change Macro Event
Before Delete Macro Event
More information is located here:
https://msdn.microsoft.com/en-us/library/office/dn124692.aspx
https://support.office.com/en-us/article/Create-a-data-macro-b1b94bca-4f17-47ad-a66d-f296ef834200
Access the GUI environment vs Jet the database format are separate things.
If you are using an Access database as a backend - it's just the JET functionality you can work with. Access the GUI (which includes VBA) runs on the client machine and there is no automated trigger functionality.
If your program is the only program using the Access file, then it should know when a table is being updated and execute some code in place of a trigger.
Otherwise, you need another application/service running all the time that is checking the access file tables for updates (maybe you have some update_date type of field on your tables?).
When an Access database file gets written to, it's date/time stamp changes. I suppose you could try using a file monitor to detect changes to the file, and then examine the file to see what has changed.
It would help if the Access database has LastModified date/time columns in the tables.
If you are using Jet (i.e. the data is stored in an MDB file back end) then the only places you can run code would be in the After Update Event in a Form. The problem here of course is if the data is changed without using the form then the event will not fire.
If you are using MS Access 2003 then to run a Web Service you can download the Microsoft Office 2003 Web Services Toolkit Click Here to download
If you are stuck in VBA it gets a little rough. One way to go would be to have a form with timer in it (you could have it open invisibly. The timer could check the table, say once a minute (or whatever interval seems suitable) for changes in record count, and verify the table still exists. (code below)
But personally this isn't what I would recommend that you do. Access is notorious for corruption. When used as a simple back end you are fairly safe most of the time, but to have it running a monitor, means the file is always open. This is basically playing Russian Roulette with your database. At minimum I would link to your database from another Access file and monitor the linked tables, that way if your monitor crashes, you don't take the production DB with you. Finally, make sure that you don't query too often, as I'd hate to see you be the sole cause of the website timing out:)
Option Explicit
Private m_lngLstRcrdCnt_c As Long
Private Sub Form_Open(Cancel As Integer)
Const lngOneMinute_c As Long = 60000
Me.TimerInterval = lngOneMinute_c
End Sub
Private Sub Form_Timer()
Const strTblName_c As String = "Foo"
Const strKey_c As String = "MyField1"
Dim rs As DAO.Recordset
Dim lngRcrdCnt As Long
If TableExists(strTblName_c) Then
Set rs = CurrentDb.OpenRecordset("SELECT Count(" & strKey_c & ") FROM " & strTblName_c & ";", dbOpenSnapshot)
If Not rs.EOF Then lngRcrdCnt = Nz(rs.Fields(0&).Value, 0&)
rs.Close
If lngRcrdCnt <> m_lngLstRcrdCnt_c Then
m_lngLstRcrdCnt_c = lngRcrdCnt
'Number of records changed, do something.
End If
Else
'Table is deleted, do something.
m_lngLstRcrdCnt_c = -1
End If
End Sub
Private Function TableExists(ByVal name As String) As Boolean
Dim tdf As DAO.TableDef
On Error Resume Next
Set tdf = CurrentDb.TableDefs(name)
If LenB(tdf.name) Then 'Cheap way to catch broken links.
Set SafeGetTable = tdf
End If
End Function