I am trying to set field values in a table using .Value, but using a variable for the field name (rs3!variable.Value=anothervariable), but it keeps giving me a runtime error (3265 - Item not found in collection). I have tried placing {} and () around the variable, and it did not help. Anyone know how I use a variable for the field name?
Pertinent Code:
Private Sub GetCMLData_Click()
Dim IPinfo1 As String
Dim rs3 As Recordset
Set rs3 = db.OpenRecordset("CMLData", dbOpenDynaset)
Dim AIP2 as string
AIP2="SomeValue"
rs3.AddNew
rs3!IPinfo1.Value = AIP2(i)
rs3.Update
End Sub
instead of using:
rs3!variableName.Value = ...
you would use:
rs3.Fields(variableName) = ...
Or just - as the Value property of a field is the value it holds:
rs(IPinfo1).Value = AIP2
Related
Silly question but I got lost.
In a VBA function I've some text which contains a string representing a listbox control name (ctrlName is the variable containing the control name).
VarText should give back the value of the selected (row/column) from listbox (error occurred here).
Function getString_email(..)
Dim ctrlName As String
Dim getString_email as String
Dim sBody as String
Dim ctl As Control
Dim frm As Form
...
...
sBody = RS("Body")
ctrlName = Mid(sBody, StartVar, EndVar - StartVar)
Set frm = Forms("frmCatalogue")
VarText = frm.Controls(ctrlName)
Set frm = Nothing
...
...
getString_email = Replace(sBody, ctrlName, VarText)
...
error: Run-time error 2465. can't find the field referred to in your expression.
Any help will be great!
I am using Access 2010. How do I get the information in a recordset from one function moved into a different function? The following code is giving me an object variable not set error:
Function Main()
Dim rs as DAO.RecordSet
Dim i as integer
Set rs = QueryResults(i)
Do While Not rs.EOF
debug.print rs!result
rs.MoveNext
Loop
End Function
Function QueryResults(i as Integer) as DAO.RecordSet
Dim stQuery as String
Dim rsResults as DAO.RecordSet
Dim i2 as Integer
i2 = i
stQuery = "Select query that uses i2 to get results"
Set rsResults = CurrentDb.OpenRecordset(stQuery)
End Function
I can step through and see that the QueryResults function is working. I can print out each line from rsResults and see that it has what I want. The problem comes when the code hits the "do while not rs.EOF" line. It says that rs was never set to anything.
What am I doing wrong? Both functions are in the same module. It seems like it shouldn't be that hard to get results from one function into another function.
When you want a function to return something, you must assign that something to the function name.
Change the last part of your QueryResults function to this:
'Set rsResults = CurrentDb.OpenRecordset(stQuery)
Set QueryResults = CurrentDb.OpenRecordset(stQuery)
End Function
Does anyone know how to retrieve the seed and increment of an auto increment field (aka COUNTER, or "AutoNumber" in the Access UI) in a Jet (MS Access) database?
I have enumerated all properties of the corresponding DAO.Field object, ADO.Field object, and ADOX.Column object, and have not been able to identify anything. Any method is acceptable, including whacky hacks of the MSys* tables or native method calls.
Background:
In Jet SQL, you can create an auto-incrementing column with a custom seed and increment with the DDL data type clause COUNTER(seed, increment), as in:
CREATE TABLE ODD_INCREMENTER (
ID_COL COUNTER(-52098, 42)
, TEXT_COL VARCHAR(50)
)
Which creates the following table (some data added for demonstration):
You can use ADOX
Dim cat As New ADOX.Catalog
Dim tbl As ADOX.Table
Dim col As ADOX.Column
Set cat.ActiveConnection = CurrentProject.Connection
Set tbl = cat.Tables("Table1")
Set col = tbl.Columns("AKey")
'Next autonumber
lngSeed = col.Properties("Seed")
Allen Browne has a fairly detailed reference: http://allenbrowne.com/ser-40.html
Consider using late binding instead of adding a reference.
You can get the increment in addition to the seed by inspecting its property.
Public Sub SeedAndIncrement(ByVal pTable As String, _
ByVal pAutonumField As String)
Dim cat As Object
Dim objColumn As Object
Set cat = CreateObject("ADOX.Catalog")
Set cat.ActiveConnection = CurrentProject.Connection
Set objColumn = cat.Tables(pTable).Columns(pAutonumField)
Debug.Print "Seed: " & objColumn.Properties("Seed")
Debug.Print "Increment: " & objColumn.Properties("Increment")
Set objColumn = Nothing
Set cat = Nothing
End Sub
I have a variable strFunction, then I have another string strName = "strFunction" , what I want to know is how can I get the value of strFunction by using strName.
For example, something like getValue(strName) gives me the value of strFunction. Is it possible in Access VBA?
Thanks!
EDIT:
I have a strFunction string, it's a const string.
In my code I want to use Len("strFunction") to test the length of it, but what i got is the length "strFunction". So I need a get-value-out-of-variable-name function. I have tried Eval(), but it cannot do this, even I write a get_strFunction(), eval("get_strFunction()") gives me error, telling me it cannot find it.
Private Const strFunction as String = "FilterByType_1"
Private Function get_strFunction()
get_strFunction = strFunction
End Function
"I have a variable strFunction, then I have another string strName = "strFunction" , what I want to know is how can I get the value of strFunction by using strName."
Instead of a variable, strFunction could be the key for an item in a VBA collection.
Public Sub darkjh()
Dim strName As String
Dim col As Collection
Set col = New Collection
col.Add "FilterByType_1", "strFunction"
strName = "strFunction"
Debug.Print col(strName)
Set col = Nothing
End Sub
Edit: Instead of a VBA collection, you could use a Scripting.Dictionary.
Dim strName As String
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
dict.Add "strFunction", "FilterByType_1"
strName = "strFunction"
Debug.Print dict(strName)
Set dict = Nothing
Option Compare Database
Dim a As String
Dim b As String
Public Sub test()
a = "b"
b = "test-string"
Debug.Print Eval("get" & a & "()")
End Sub
Public Function getB() As String
getB = b
End Function
Output
>>test
test-string
eval(a) did not work, so I had to write a "getter" for the variable and eval that function: eval("get" & a & "()").
how can i grab a record (and eventually delete it) using linq2sql without knowing the type at compile time?
so far i've got
Sub Delete(ByVal RecordType As String, ByVal ID As Integer)
Dim dummy = Activator.CreateInstance(MyAssembly, RecordType).Unwrap
Dim tbl = GetTable(dummy.GetType)
tbl.DeleteOnSubmit(dummy)
End Sub
but of course the dummy is not an actual record, its just a dummy
i don't want to use direct sql (or executecommand) as there's business logic going on at deletion in the datacontext partial class
can this be done somehow?
thank you very much!
EDIT
in response to striplinwarior, i edited my code to:
Sub Delete(ByVal RecordType As ObjectType, ByVal ID As Integer)
Dim dummy = Activator.CreateInstance(ObjectType.Account.GetType.Assembly.FullName, RecordType.ToString).Unwrap
SetObjProperty(dummy, PrimaryKeyField(RecordType), ID)
Dim tbl = GetTable(dummy.GetType)
tbl.Attach(dummy)
tbl.DeleteOnSubmit(dummy)
SubmitChanges()
End Sub
this does fire off the deletion code correclty, but also seems to try to add the record first to the db, as i get a sqlexception that some "not null" fields are empty, which i guess is true about the dummy record, as the only thing this has is the primarykey, else is all empty. so i tried the other code u posted (something i anyways always wanted to have) and that works excellent!
hers my current code:
Function LoadRecord(ByVal RecordType As String, ByVal RecordID As Integer) As Object
Dim dummy = Activator.CreateInstance(AssemblyName, RecordType).Unwrap
Dim rowType = dummy.GetType
Dim eParam = Expression.Parameter(rowType, "e")
Dim idm = rowType.GetProperty(PrimaryKeyField(RecordType))
Dim lambda = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(eParam, idm), Expression.Constant(RecordID)), eParam)
Dim firstMethod = GetType(Queryable).GetMethods().[Single](Function(m) m.Name = "Single" AndAlso m.GetParameters().Count() = 2).MakeGenericMethod(rowType)
Dim tbl = GetTable(rowType)
Dim obj = firstMethod.Invoke(Nothing, New Object() {tbl, lambda})
Return obj
End Function
Sub Delete(ByVal RecordType As String, ByVal RecordID As Integer)
Dim obj = LoadRecord(RecordType, RecordID)
Dim tbl = GetTable(obj.GetType)
tbl.DeleteOnSubmit(obj)
SubmitChanges()
End Sub
Thank You
The only way I can think of is to use the model information from your database mapping to figure out which member represents the primary key:
Dim primaryKey = (From t In db.Mapping.GetTables() _
Where t.RowType.Type = tableType _
Let keyMember = (From dm In t.RowType.DataMembers where dm.IsPrimaryKey).FirstOrDefault() _
Select keyMember.Member.Name).First()
(I'm using LinqPad here: I assume typical LINQ to SQL models have this mapping information available.)
Then use reflection to set the value of that key member on the dummy item you've created. After that, you need to attach the dummy to the table before trying to delete it, passing false as a second parameter to tell LINQ to SQL that you don't actually want to update the object using its current values, but that it should track changes from here on.
tbl.Attach(dummy, false)
tbl.DeleteOnSubmit(dummy)
db.SubmitChanges()
Does that make sense?
Edit
When you're only deleting an object, you don't necessarily have to get the record from the database. If you set the ID value of the object and then attach it to the context (as shown above), LINQ to SQL will treat it as if it were retrieved from the database. At that point, calling DeleteOnSubmit should tell the context to construct a DELETE statement in SQL based on that object's primary key value.
However, if you need to retrieve the object for some purpose other than deletion, you'll need to construct an expression to represent the query for that object. So, for example, if you were writing the query manually, you would say something like:
Dim obj = tbl.First(Function(e) e.Id = ID)
So to dynamically build the lambda expression inside the parentheses, you might do something like this:
Dim eParam = Expression.Parameter(rowType, "e")
Dim lambda = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(eParam, idMember), Expression.Constant(ID)), eParam)
Then you would need to use reflection to invoke the generic First method:
Dim firstMethod = GetType(Queryable).GetMethods().[Single](Function(m) m.Name = "Single" AndAlso m.GetParameters().Count() = 2).MakeGenericMethod(rowType)
Dim obj = firstMethod.Invoke(Nothing, New Object() {tbl, lambda})