Classic asp - editing and saving a record? [duplicate] - vbscript

I'm primarily an PHP developer, but I have some old ASP one of our previous developers made that broke and I can't figure out how to fix it. We have a program that sends some variables to a listener page that compares that data to registration codes an msSQL database and then lets the program know if the registration code is valid.
I'm getting the following error where
.Parameters.Append .CreateParameter("#code", adVarChar, 1, 50, x)
is line 134:
ADODB.Parameters error '800a0e7c'
Parameter object is improperly defined. Inconsistent or incomplete information was provided.
/checkregistrationpro.asp, line 134
I've already specified any named constants in an include file that I have not included in the code, so it isn't to do with that.
My Connection String (I've already verified that these settings are right):
set conn = Server.CreateObject("ADODB.Connection")
set cmd = Server.CreateObject("ADODB.Command")
sConnString = "Provider=sqloledb; Data Source=MYDATASOURCE; Initial Catalog=MYCATALOG; User ID=MYUSERID; Password='MYPASSWORD';"
conn.Open sConnString
My Code:
...
Function BlockInjectCode(StrVal)
BlockInjectCode = Replace(StrVal,"--","")
BlockInjectCode = Replace(BlockInjectCode,"'","")
BlockInjectCode = Replace(BlockInjectCode,"""","")
if instr(lcase(BlockInjectCode),"<") > 0 then
BlockInjectCode = ""
end if
End Function
x = BlockInjectCode(Request.QueryString("rid"))
uid = BlockInjectCode(Request.QueryString("uid"))
chkcode = BlockInjectCode(Request.QueryString("Code"))
CheckPro = BlockInjectCode(Request.QueryString("pro"))
CheckProProd = BlockInjectCode(Request.QueryString("prod"))
CheckProMac = BlockInjectCode(Request.QueryString("mac"))
MacAdd = CheckProMac
CodeValid = False
if x <> "" and uid <> "" then
'-- Get information about this registration code.
sqlStr = "select * from MYTABLE where Code = ? and IsValid = 1"
set cmdCodes = Server.CreateObject("ADODB.Command")
Set cmdCodes.ActiveConnection = Conn
cmdCodes.CommandText = sqlStr
with cmdCodes
.Parameters.Append .CreateParameter("#code", adVarChar, 1, 50, x)
end With
Set rsCodes = cmdCodes.execute
...

Common occurrence is likely you do not have adVarChar defined, so the CreateParameter() method is "improperly defined".
This is just an example of one of the many named constants found in the ADODB Library. A messy approach to dealing with this is to just define the value yourself something like;
Const adVarChar = 200
The problem with this approach is you then have to define all the named constants which can be a headache. Another approach is to just skip the whole named constants thing and just use the integer values, so the call would be;
.Parameters.Append .CreateParameter("#code", 200, 1, 50, x)
However this isn't easy to read although it looks as though you are doing this already with the ParameterDirectionEnum value of 1 which is the named constant adParamInput in the ADODB Library. Regardless I wouldn't recommend this approach.
A slightly better approach is to use an #include directive so that it includes in the calling page all the named constant definitions you could want and this is how most do it. Microsoft provide a pre defined file for this very purpose with IIS (or possibly the MDAC library installation I'm not sure off the top of my head) known as adovbs.inc or adovbs.asp, by including this file your page would have access to all the named constant definitions within.
The reason for all this is VBScript doesn't support type libraries, so in a Client scenario defining them yourself or copying and pasting from the adovbs.inc file is your only option. However in a Server scenario we still have the power of IIS which lets us do some funky things.
Wouldn't it be nice if the Type Library could just be added once and you don't have to worry about it?, no annoying constants to have to define? Let's face it they already exist in the Type Library so why can't we get them from there? Well turns out we can thanks to the METADATA directive.
Here is an example;
<!--
METADATA
TYPE="TypeLib"
NAME="Microsoft ActiveX Data Objects 2.5 Library"
UUID="{00000205-0000-0010-8000-00AA006D2EA4}"
VERSION="2.5"
-->
The beauty of this approach is you can use for any Type Library (ideally exposed to COM) and you can define in one page, or add it into the global.asa to have defined across the entire Web Application.
With this approach you are then safe to use code like;
.Parameters.Append .CreateParameter("#code", adVarChar, adParamInput, 50, x)
Useful Links
VBScript ADO Programming
Answer to ASP 3.0 Declare ADO Constants w/out Including ADOVBS.inc
Answer to Passing Parameters to a Stored Procedure using ASP
Using METADATA to Import DLL Constants

In the places where you are defining adVarChar, and other ADO magic numbers, get rid of them completely.
Instead add this to the top of your global.asa (create one if it doesn't) exist.
<!--METADATA TYPE="TypeLib" file="C:\Program Files (x86)\Common Files\System\ado\msado15.dll" -->
This will import the msado15 type library which already has all of those magic numbers defined. It will pull in all the defines for you automatically. Meaning you won't have to define adVarChar etc yourself, the metadata tag will import them automatically for you. Credit to #Lankymart for this as his comment lead me to discovering this and figuring it out, and it works great.
Now, turn create a test asp page that's empty and add some test code to it with option explicit on.
<%
Option Explicit
Response.Write "adVarChar: " & adVarChar
%>
If you get an error that adVarChar is not defined, then msado15.dll is not on the server. So you will need to contact godaddy etc to have them tell you the path to whatever version of MSADO is on there and change your metadata tag to reference the right version.

Related

ADODB.Parameters error '800a0e7c' Parameter object is improperly defined. Inconsistent or incomplete information was provided

I'm primarily an PHP developer, but I have some old ASP one of our previous developers made that broke and I can't figure out how to fix it. We have a program that sends some variables to a listener page that compares that data to registration codes an msSQL database and then lets the program know if the registration code is valid.
I'm getting the following error where
.Parameters.Append .CreateParameter("#code", adVarChar, 1, 50, x)
is line 134:
ADODB.Parameters error '800a0e7c'
Parameter object is improperly defined. Inconsistent or incomplete information was provided.
/checkregistrationpro.asp, line 134
I've already specified any named constants in an include file that I have not included in the code, so it isn't to do with that.
My Connection String (I've already verified that these settings are right):
set conn = Server.CreateObject("ADODB.Connection")
set cmd = Server.CreateObject("ADODB.Command")
sConnString = "Provider=sqloledb; Data Source=MYDATASOURCE; Initial Catalog=MYCATALOG; User ID=MYUSERID; Password='MYPASSWORD';"
conn.Open sConnString
My Code:
...
Function BlockInjectCode(StrVal)
BlockInjectCode = Replace(StrVal,"--","")
BlockInjectCode = Replace(BlockInjectCode,"'","")
BlockInjectCode = Replace(BlockInjectCode,"""","")
if instr(lcase(BlockInjectCode),"<") > 0 then
BlockInjectCode = ""
end if
End Function
x = BlockInjectCode(Request.QueryString("rid"))
uid = BlockInjectCode(Request.QueryString("uid"))
chkcode = BlockInjectCode(Request.QueryString("Code"))
CheckPro = BlockInjectCode(Request.QueryString("pro"))
CheckProProd = BlockInjectCode(Request.QueryString("prod"))
CheckProMac = BlockInjectCode(Request.QueryString("mac"))
MacAdd = CheckProMac
CodeValid = False
if x <> "" and uid <> "" then
'-- Get information about this registration code.
sqlStr = "select * from MYTABLE where Code = ? and IsValid = 1"
set cmdCodes = Server.CreateObject("ADODB.Command")
Set cmdCodes.ActiveConnection = Conn
cmdCodes.CommandText = sqlStr
with cmdCodes
.Parameters.Append .CreateParameter("#code", adVarChar, 1, 50, x)
end With
Set rsCodes = cmdCodes.execute
...
Common occurrence is likely you do not have adVarChar defined, so the CreateParameter() method is "improperly defined".
This is just an example of one of the many named constants found in the ADODB Library. A messy approach to dealing with this is to just define the value yourself something like;
Const adVarChar = 200
The problem with this approach is you then have to define all the named constants which can be a headache. Another approach is to just skip the whole named constants thing and just use the integer values, so the call would be;
.Parameters.Append .CreateParameter("#code", 200, 1, 50, x)
However this isn't easy to read although it looks as though you are doing this already with the ParameterDirectionEnum value of 1 which is the named constant adParamInput in the ADODB Library. Regardless I wouldn't recommend this approach.
A slightly better approach is to use an #include directive so that it includes in the calling page all the named constant definitions you could want and this is how most do it. Microsoft provide a pre defined file for this very purpose with IIS (or possibly the MDAC library installation I'm not sure off the top of my head) known as adovbs.inc or adovbs.asp, by including this file your page would have access to all the named constant definitions within.
The reason for all this is VBScript doesn't support type libraries, so in a Client scenario defining them yourself or copying and pasting from the adovbs.inc file is your only option. However in a Server scenario we still have the power of IIS which lets us do some funky things.
Wouldn't it be nice if the Type Library could just be added once and you don't have to worry about it?, no annoying constants to have to define? Let's face it they already exist in the Type Library so why can't we get them from there? Well turns out we can thanks to the METADATA directive.
Here is an example;
<!--
METADATA
TYPE="TypeLib"
NAME="Microsoft ActiveX Data Objects 2.5 Library"
UUID="{00000205-0000-0010-8000-00AA006D2EA4}"
VERSION="2.5"
-->
The beauty of this approach is you can use for any Type Library (ideally exposed to COM) and you can define in one page, or add it into the global.asa to have defined across the entire Web Application.
With this approach you are then safe to use code like;
.Parameters.Append .CreateParameter("#code", adVarChar, adParamInput, 50, x)
Useful Links
VBScript ADO Programming
Answer to ASP 3.0 Declare ADO Constants w/out Including ADOVBS.inc
Answer to Passing Parameters to a Stored Procedure using ASP
Using METADATA to Import DLL Constants
In the places where you are defining adVarChar, and other ADO magic numbers, get rid of them completely.
Instead add this to the top of your global.asa (create one if it doesn't) exist.
<!--METADATA TYPE="TypeLib" file="C:\Program Files (x86)\Common Files\System\ado\msado15.dll" -->
This will import the msado15 type library which already has all of those magic numbers defined. It will pull in all the defines for you automatically. Meaning you won't have to define adVarChar etc yourself, the metadata tag will import them automatically for you. Credit to #Lankymart for this as his comment lead me to discovering this and figuring it out, and it works great.
Now, turn create a test asp page that's empty and add some test code to it with option explicit on.
<%
Option Explicit
Response.Write "adVarChar: " & adVarChar
%>
If you get an error that adVarChar is not defined, then msado15.dll is not on the server. So you will need to contact godaddy etc to have them tell you the path to whatever version of MSADO is on there and change your metadata tag to reference the right version.

Passing Parameters to a Stored Procedure using ASP

I'm trying to pass some parameters to a SQL stored procedure in my classic ASP. I've seen several posts on this and not sure what I'm doing wrong as I don't seem to see my discrepancy.
set conn = CreateObject("ADODB.Connection")
conn.open ("DSN=SERVER;UID=username;PWD=pwd;Database=MyDatabase")
set cmd = Server.CreateObject("ADODB.Command")
set cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = my_proc
cmd.Parameters.Refresh
cmd.Parameters(1) = "MyParam"
set rs = cmd.execute
I'm getting the error
Arguments are of the wrong type, are out of acceptable range, or are in conflict
with one another.
on the line cmd.CommandType = adCmdStoredProc. I also tried to do it the following way with the same error
set conn = CreateObject("ADODB.Connection")
conn.open ("DSN=SERVER;UID=username;PWD=pwd;Database=MyDatabase")
set cmd = Server.CreateObject("ADODB.Command")
set cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = my_proc
cmd.Parameters.Refresh
cmd.Parameters.Append cmd.CreateParameter("#MyParam, adVarWChar, adParamInput, 50, "test")
set rs = cmd.execute
#KekuSemau is correct but let me a suggest a more efficient and manageable approach then using the adovbs constants file.
METADATA allows you to define a reference to the DLLs constants even if your using Late Binding as is the case in a Classic ASP environment. It's probably worth mentioning that you can add METADATA references in individual pages but then again why would you?
To use it simply add the METADATA tag to your global.asa file (should be located in the root of your Web Application).
<!--
METADATA TYPE="typelib" FILE="C:\Program Files\Common Files\System\ADO\msado20.tlb"
-->
Depending on the system the ADO Type Library maybe different, adjust the FILE attribute accordingly.
I use this approach in all my applications mainly for referencing constants in the ADO and CDO Type Libraries.
ADO Type Library
<!--
METADATA
TYPE="typelib"
FILE="c:\program files\common files\system\ado\msado15.dll"
-->
CDO Type Library
<!--
METADATA
TYPE="typelib"
UUID="CD000000-8B95-11D1-82DB-00C04FB1625D"
NAME="CDO for Windows 2000 Library"
-->
These are examples of my own personal references, file locations maybe different whereas UUID attributes should be exactly the same.
IMPORTANT:
Remember to remove any references to adovbs constant include file (adovbs.inc or adovbs.asp commonly) when using METADATA approach in your global.asa or you will get a
Name redefined error
Also METADATA is only available in IIS 4.0 and above.
Useful Links
Using METADATA to Import DLL Constants (Recommended reading)
You use ADO through late binding, which means that the constants like adCmdStoredProc, adParamInput etc. are unknown to your code (so they are always 0).
You can either look them up and define the ones you need as a constant in your code (or use the numbers directly, but that's not well readable if you edit the code again later).
Or take a look here on msdn - you may find a file that defines all the constants at
c:\Program Files\Common Files\System\ado\adovbc.inc.
I think there is only a very small piece that you are doing wrong:
set conn = CreateObject("ADODB.Connection")
conn.open ("DSN=SERVER;UID=username;PWD=pwd;Database=MyDatabase")
set cmd = Server.CreateObject("ADODB.Command")
set cmd.ActiveConnection = conn
cmd.CommandType = 4 ' adCmdStoredProc constant is not defined in your context
cmd.CommandText = my_proc
cmd.Parameters.Refresh
cmd.Parameters(1).value = "MyParam"
set rs = cmd.execute
The ADO constants are probably undefined, and also (but not sure) the parameter should be assign via its value property.

Creating a view and agent in multiple databases

The problem I am encountering is that some of the messages are not accessible by the user ID file, I would like to skip these files instead of the agent crashing out. The error message received is as follows:
Using the view approach if this happened I was able to delete the document temporarily and re-run the agent but if there is a way to skip documents it would be a great help.
Thanks for the help guys.
Ok I have amended the code to a point where I am almost comfortable with it.
Sub Initialize
Dim s As New notessession
Dim db As notesdatabase
Dim view As notesview
Dim doc As notesdocument
Dim nextdoc As notesdocument
Set db = s.currentdatabase
If view Is Nothing Then
Set view = db.CreateView("Encrypted",{Encrypt="1"})
End If
Set doc = view.getfirstdocument
On Error Goto ErrorHandler
While Not doc Is Nothing
nextDocument:
Set nextdoc = view.getnextdocument(doc)
'The below loop is mandatory to ensure that all $File entries are unecrypted
Forall i In doc.items
If i.isencrypted Then
i.isencrypted=False
End If
End Forall
'Must have at least 1 field encrypted in order to call Encrypt method
Dim temp As New NotesItem(doc,"tempjunk","temp")
temp.IsEncrypted=True
Call doc.encrypt
Call doc.save(True, False)
'This portion can now remove the fields relative to encrypting the
'single token encrypted field.
Call doc.removeitem("$Seal")
Call doc.removeitem("$SealData")
Call doc.removeitem("SecretEncryptionKeys")
Call doc.removeitem("Encrypt")
Call doc.removeItem("tempjunk")
Call doc.save(True, False)
Set doc = nextdoc
Wend
Exit Sub
ErrorHandler:
On Error Resume nextDocument
Exit Sub
End Sub
The error handling is not playing nice;
On Error Resume nextDocument is showing up as an error.
I have tried suppressing all of the error warnings which seems to attempt to strip the encryption but I think they body of the messages is being destroyed as a result.
It is no problem to create an agent in a container database and let that agent access documents in all "target" databases and modify them accordingly - No need to copy that agent to all databases.
Only restriction: If the databases are on another server, then on the server security tab of the target server you have to enter the server with the container database as trusted server.
AND: If your agent runs longer than the allowed maximum run time for agents on the server, then it will be killed prematurely.
There is no need to create views in the target databases, you can use NotesDatabase.Search() to get the corresponding documents in the databases...
You can create views by copying them from another database. Say you create a view "Encrypted" in your db with the agent.
Then add a piece of code to get a handle of this view as a NotesDocument:
Dim dbThis As NotesDatabase
Dim viewTemplate As NotesView
Dim docView As NotesDocument
Set dbThis = s.currentDatabase
Set viewTemplate = dbThis.getView("Encrypted")
Set docView = dbThis.Getdocumentbyunid(viewTemplate.Universalid)
In the agent loop, test if view Encrypted exists, if not copy the "view template":
Set view = db.getview("Encrypted")
If view Is Nothing Then
Call docView.Copytodatabase(db)
Set view = db.getview("Encrypted")
End If
Finally, if you insist, a similar procedure might be used to copy the agent to all databases, but for me the idea of running the agent in one db sounds better.
Edited: In the view of full disclosure - of course you can create a view (I guess that was the original question).
If view Is Nothing Then
Set view = db.Createview("Encrypted", {Encrypt="1"})
End If
Or do one-shot dbSearch suggested by Torsten, with a good re-mark of Richard - if you intend to run your code several times - say if encrypted documents might get created again or re-encrypted, rather go for the view.
My method is a bit old fashioned (pre-dates availability of createView) and works well if you need more than selection formula, so you can pre-build a complicated view for re-use.
Performance-wise: whatever method you will choose either creating view using createView or copying from other db or doing dbSearch there is going to be a certain slow-down while the view gets built or dbSearch executes. Karl-Henry's approach will avoid this search/view build, but will be relatively slow if there are not many encrypted documents.
Whichever method you choose - here is a small tip to boost performance. Make your loops like this to release memory as you go; for example, assuming Karl-Henry's approach:
Dim doc1 as NotesDocument
Set doc = col.GetFirstDocument()
Do Until doc Is Nothing
Set doc1 = col.GetNextDocument(doc)
formname = doc.GetItemValue("Form")(0)
If IsElement(exclude(formname))=False Then
Call RemoveEncryption(doc) '*** Your function to remove encryption
End If
' releasing memory when processing thousands of documents improves performance and avoids crashes
Delete doc
Set doc = doc1
Loop
Now again, as you are talking only about migration (so one shot) of 20+ databases, the speed or implementation details should not be that critical.
If you have to process all (or almost all) documents in each database, you can use db.AllDocuments. It is more efficient than using db.Search() with an #All formula.
If you want to exclude certain documents, perhaps based on the form name, I would build a list of forms to exclude, and then use IsElement to check each document being processed against that list.
Dim exclude List As Boolean
exclude("FormA")=True
exclude("FormB")=True
Set col = db.AllDocuments
Set doc = col.GetFirstDocument()
Do Until doc Is Nothing
formname = doc.GetItemValue("Form")(0)
If IsElement(exclude(formname))=False Then
Call RemoveEncryption(doc) '*** Your function to remove encryption
End If
Set doc = col.GetNextDocument(doc)
Loop
Something like that. By the way, you can create the list as any data type. I just choose Boolean as it is a small data type, and that it makes the code easier to read. The IsElement() function just check if the element exists, it does not use the value you set.
You would wrap the code above in a function and call it once per database.
Appended answer, based on additional info in original question:
That should not be hard, just add error handling to your code.
Before you start to loop throung the document:
On Error Goto errHandler
Before you get the next document in the loop:
nextDocument:
At the end of your code:
Exit Sub
errHandler:
Resume nextDocument
End Sub
Try that.

vbscript - attempt to automate updating upgrade table at compile time gives error object required

I am trying to automate a process to update a wise for windows package at compile time to update the productcode, package code, productversion, and the update table versionmax values.
I can successfully update the property table and the summary information for the Package Code. However, the update table is giving me problems. There are several entries in this table.
I can enumerate the existing entries, but I cannot update the existing entries. Each time I attempt to I get an error "Exception: Object required 'project.WTables(...).WRows.Row(...)'
The syntax I am using is identical to the preceding calls to update the ProductCode, ProductVersion, and Package Code.
I am using vbscript.
I am passing in the product version and full path to the wise wsi project file. In the UpdateUpgradeTable function aUpgradeGuids populate correctly with a collection of upgrade codes as I expect. All I want to do now is to change the VersionMax value for each of these codes to the current wiseProductVersion. However, vbscript seems to have some problem with the object WRows.Row(a(i)), which is an actual GUID.
I have looked at other sample scripts in the automation section of help and it does support the use of variables, and it does not look like the variables require quotes like straight text does. I am not even sure what it means, object required. Project is definitely an object. I have confirmed that. I have even tried this by inserting straight text inside the function but it still fails. I have tried it with tblProperty.WRows.Row(...) but it fails the same way. I have tried calling it with a good Upgrade Code outside of the For loop right after Set tblProperty = ... and it still fails. This type of structure works in all previous tables. It has me puzzled. Any ideas? I think this may transcend just Wise for Windows and is perhaps generic to msi as well so I am going to post under MSI too.
I have a sub main that looks like this:
Dim wiseInstallDir: wiseInstallDir = WScript.Arguments(0)
Dim wiseProductVersion: wiseProductVersion = WScript.Arguments(1)
Sub main()
Set wise = CreateObject("WfWi.Document")
Dim nResult
nResult = wise.Open (wiseInstallDir)
UpdateProductVersion wise
... 'other functions
UpdateUpgradeTable wise
wise.Save wiseInstallDir
End Sub
'This function works properly
Sub UpdateProductVersion(project)
Set tblProperty = project.WTables("Property")
tblProperty.WRows.Row("ProductVersion").WColumns("Value").Data=wiseProductVersion
End Sub
Sub UpdateUpgradeTable(project)
Set tblProperty = project.WTables("Upgrade")
Dim tmpRow,count: count = 0
Dim aUpgradeGuids: Set aUpgradeGuids = CreateObject("Scripting.Dictionary")
Const UPGRADECODE = 0
For Each tmpRow In tblProperty.WRows
Dim tRow: tRow=tmpRow.Key
Dim values: values=Split(tRow, ",")
aUpgradeGuids.Add count,values(0)
count=count + 1
Next
a = aUpgradeGuids.Items
For i = 0 To aUpgradeGuids.Count - 1
project.WTables("Upgrade")._
WRows.Row(a(i)).WColumns("VersionMax").Data=wiseProductVersion
Next
End Sub
main
EDIT:
'updated UpdateUpgradeTable
Sub UpdateUpgradeTable(project)
Set tblProperty = project.WTables("Upgrade")
Dim tmpRow
'Get the UpgradeCode for each current record and change the VersionMax value for that record.
For Each tmpRow In tblProperty.WRows
Dim tRow: tRow=tmpRow.Key
Dim values: values=Split(tRow, ",")
tblProperty.WRows.Row(values(0)).WColumns("VersionMax").Data=wiseProductVersion
Next
End Sub
I think I know the answer. I still do not have it working 100% but I found additional documentation for the Row method stating for tables with multiple key columns, commas separate key values. I have inserted the value(0), value(1), ... but I am now getting a different error. I will update once I get this working.
The upgrade table has 5 primary key values.
<!-- language: lang-vbs -->
Set rows = tblProperty.WRows
Set row = tblProperty.WRows.Row(values(UPGRADECODE), values(VERSIONMIN), values(VERSIONMAX), values(LANGUAGE), values(ATTRIBUTES))
tblProperty.WRows.Row(values(UPGRADECODE),values(VERSIONMIN),values(VERSIONMAX),values(LANGUAGE),values(ATTRIBUTES)).WColumns("VersionMax").Data=wiseProductVersion
Note that the first Set rows=... returns a valid object with its corresponding methods.
The second line fails with the message:
Exception: Wrong number of arguments or invalid property assignment: 'tblProperty.WRows.Row'
Below are the 5 primary keys for the upgrade table.
values (UPGRADECODE)
values (VERSIONMIN)
values (VERSIONMAX)
values (LANGUAGE)
values (ATTRIBUTES)
Is there another way to update the upgrade table? Is there something I am missing?
According to documentation the WRows object is a child of WTable. And it is returning a valid object for me. It has the following method:
WRow Row(BSTR strKeyValue): returns a WRow given its key value. For tables with multiple key columns, commas separate key values.
Row() is the default method.
However, my comma separated key values construct above is failing and I am not sure where to turn now. Has anyone ever worked with this before and had it working?

VBA - User-defined type not defined

I am trying to update an VBA module to use the System.Windows.Forms.FolderBrowserDialog class. I declared my object as follows:
Dim MyFolderBrowser As New System.Windows.Forms.FolderBrowserDialog
Running this gave me the error User-defined type not defined. I figured the compiler didn't know about that class so I tried going to Tools > References and adding Systems_Windows_Forms, but I'm still getting the same error. Does anyone know what I'm missing here? Do I need a reference to the library in my code as well?
System.Windows.Forms.FolderBrowserDialog looks like something from .Net to me, not VBA.
You can use Application.FileDialog in Access VBA. This sample uses late binding and allows the user to select a folder from a browse dialog.
Const msoFileDialogFolderPicker As Long = 4
Dim objFileDialog As Object ' FileDialog
Set objFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
With objFileDialog
.AllowMultiSelect = False
If .Show Then
Debug.Print .SelectedItems(1)
End If
End With
If you prefer to use early binding, set a reference to the Microsoft Office [version] Object Library. You could then declare the object like this ...
Dim objFileDialog As FileDialog
And you wouldn't need to define the constant, so discard this line if using early binding ...
Const msoFileDialogFolderPicker As Long = 4

Resources