OK so I have tried a few differrent ways and searched the forums. I've found similar problems to the one I'm having, but not quite what I'm looking for.
I have a query on my database that returns 2 columns. In the first column is a code number, and the revision for the code number in the second
e.g.
Code_1 0
Code_1 1
Code_2 0
Code_2 1
Code_2 2
Now what I need to do is loop through this query and pick out the code and the maximum revision number associated with each code number and put these into another table so I would end up with
Code_1 1
Code_2 2
in my new table.
I've can't even seem to loop through the query and all I get each time is the first result. I've used Debug.Print below to show myself exactly what my loop is doing.I've done some Java and the vba loops are obv different. One way I've tried is:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb()
Set rs = db.OpenRecordset("Query_Name")
Dim i,j as Integer
Dim tempvar1, tempvar2 As Variant
For i = 0 To rs.EOF
tempvar1 = rs!Code_Number
For j = 0 to rs.EOF
tempvar2 = rs!Code_Rev
If Code_Rev > tempvar2 Then
tempvar2 = rs!Code_Rev
End If
Debug.Print(tempvar1 + tempvar2)
Next j
Next i
All I get is the first code number and revision on the list. If I can't even loop through the list properly I've no hope of creating a new table from the results I need :-/
I've also tried doing something similar with a Do While Loop but same type of result.
Please show me the error of my ways in iterating through the query and please help me create a new table from the results.
Why not a straight query?
SELECT tx.Code, Max(tx.[NewCode]) AS MaxOfC INTO New
FROM tx
GROUP BY tx.Code;
Where tx is the name of your table.
Related
I know this has probably been asked thousands of times before, but I seem to be having trouble finding an existing question that addresses this question in a wy I can understand.
My question in how can I access a value located in the last record of a table? For example, if this is my table:
personID personName personNumber
1 Sally PR32
2 Emily PR33
3 Joseph PR34
I want to access the value "PR34" (and then be able to manipulate it if possible). I know how to find the last record with Dmax, but I'm struggling to figure out how to find a value within it. I'm ultimately trying to take the value, parse the string down to just the numbers, and increment it by one (and then append the letters back on).
You can do this in a query as well:
UPDATE T
SET T.personNumber = "PR" & CLng(Replace([personNumber], "PR", "")) + 1
WHERE (((T.personID)=(SELECT Max(personID) FROM T)));
Where T is the name of your Table.
If you're in the DLookUp/DMax workflow, you can just use the following:
This gives you the ID, you already figured this out:
DMax("PersonID", "MyTable")
Then lookup the associated personNumber with that ID:
DLookUp("personNumber", "MyTable", "personID = " & DMax("PersonID", "MyTable"))
But if you want to manipulate it (or just be more efficient), using a recordset is the way to go:
'Create a recordset
Dim rs As Recordset
'Query the last value, get the personNumber
Set rs = CurrentDb.OpenRecordset("SELECT TOP 1 personNumber FROM MyTable ORDER BY personID DESC")
'Open it up for editing
rs.Edit
'Increment the number by 1
rs.Fields("personNumber").Value = Left(rs.Fields("personNumber").Value, 2) & CInt(Mid(rs.Fields("personNumber").Value, 3, Len(rs.Fields("personNumber").Value) - 2)) + 1
'Update the recordset
rs.Update
Hi I've been trying to adapt a prior stack overflow post to my situation but coming up short. I have 2 ms access tables in a parent child relationship (one to many). I'm trying to write some vba to insert 1 record into the parent table and multiple records into the child table. I saw this post which does something close to what I want but its for a one to one relationship. Could someone provide me an example of how to do this with multiple rows in the child table?
How can I make new records cascade across a one to one relationship in MS Access?
I'm using MS Access 2010 and I'm writing the vba as a module in MS Excel 2010.
It all relates to how you connect the "many" entries table to the "one" table. (Unless I'm missing the point of your question.) This example works to illustrate:
Option Explicit
Sub AddClassWithStudents()
Dim tblClass As Recordset
Dim tblStudents As Recordset
Dim db As database
Dim classID As Long
Dim newKids() As String
Dim kid As Variant
Set db = DBEngine(0).OpenDatabase("Database1.accdb")
Set tblClass = db.openrecordset("tblClasses", dbopendynaset)
Set tblStudents = db.openrecordset("tblStudents", dbopendynaset)
'--- add a new class
tblClass.AddNew
tblClass("Title").Value = "Calculus"
tblClass("Teacher").Value = "Einstein"
tblClass.Update
tblClass.Bookmark = tblClass.LastModified 'makes it the current record
classID = tblClass("ID").Value
'--- add some students
newKids = Split("Tom,Dick,Harry,Suzie,Mary", ",", , vbTextCompare)
For Each kid In newKids
tblStudents.AddNew
tblStudents("ClassID").Value = classID
tblStudents("StudentName").Value = kid
tblStudents.Update
Next kid
db.Close
Set tblStudents = Nothing
Set tblClass = Nothing
Set db = Nothing
End Sub
I have a table ("Bookings") with the field [StartHour] (I get its value from a form). I want to automatically update the value of another table field ([EndHour]) with the value [StartHour]+1hour.
How can I do this?
I found some VBA (I suppose) solutions, but I don't think I can use VBA in here. I'm talking about
= DateAdd("h", 1, [YourField])
The below code is not tested and im writing it from off the top of my head so there might be a few issues. But if you put it into the VBA editor it will show any
You'll need the microsoft DAO reference library ticked in tools>references
Open both tables in memory then edit the first record of the endhour field.
Add 1 hour to the start hour of the first table, then save in end hour field.
dim tbl1 as dao.recordset
dim tbl2 as dao.recordset
tbl1 = currentdb.openrecordset("table1")
tbl2 = currentdb.openrecordset("table2")
with tbl2
.edit
.fields("EndHour") = dateadd("h",1,tbl1("Start Hour"))
.update
end with
set tbl1 = nothing
set tbl2 = nothing
I am currently using a continuous form to a show a set of data that results in the following format (each line being one record):
1/04/13 Person1
31/03/13 Person1
30/03/13 Person1
29/03/13 Person2
28/03/13 Person1
There are 100s of these records and I would like to condense it to the following:
30/03/13 - 1/04/13 Person1
29/03/13 Person2
28/03/13 Person1
The data is from a query, so can be manipulated at the SQL level before it even gets to the form stage. I am also comfortable using macros or VBA to manipulate the form. However, I still haven't been able to find a suitable way of doing this.
I realise that this is typical behaviour for a report, but since I eventually want this to be embedded in another form as a subform, I can't use reports (can't create a subreport in a form unless I am missing something).
Any help or advice is much appreciated.
Good description of the problem. Try building your source query like this (assuming the fields are called MyDate and MyPerson and the source table is MyTable):
Select Person, min(MyDate) as StartDate, max(MyDate) as EndDate
from MyTable
group by Person
This gives you 3 fields that you can drop into your form.
Edit
Now that we have a more complete picture, the task just got more complicated, but you still have options assuming the 'events' between people don't overlap (if they do, then I can't think of how to create eventIDs afterward). In the absence of an EventID, you'll have to create one:
First, you need to move your data to a new table so that you can reorder it and add a blank field for the event ID you'll be adding in step 2.
1a. Copy MyTable into a new table. Add an extra field called EventID.
1b. To populate this table, first Delete * from TmpTbl
1c. Then something like:
Insert into TmpTbl.* from MyTable order by MyDate,MyPerson
This code will look through your temp table (TmpTbl as i call it) and add an event id.
Sub AddEventIDs()
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TmpTbl")
Dim LastPerson As String
Dim EventID As Integer
docmd.setwarnings false
While rst.EOF = False
If LastPerson <> rst.Fields("MyPerson") Then EventID = EventID + 1
LastPerson = rst.Fields("MyPerson")
rst.Edit
rst.Fields("EventID") = EventID
rst.Update
rst.MoveNext
Wend
docmd.setwarnings true
End Sub
On the On Load event of your form, add in the 2 queries and the sub routine from #1 and #2.
Your final query will be:
Select MyPerson, EventID, min(MyDate) as StartDate, max(MyDate) as EndDate
from MyTable
group by MyPerson,EventID
I need to be able to count all the NULLS in all columns of an Access 2010 table. what I mean by that specifically, is that of the 30 columns (fields) there are loads of records with partial data.
I want to count in the entire table how many are empty.
I read the article on this site titled, How to count all NULL values in table, but that referred to SQL and also, was, I am sorry to admit too complex for me.
Anyone got any futher clues?
:)
For a single field, you could use a simple query.
SELECT Count(*) AS CountOfNulls
FROM MyTable
WHERE some_field Is Null;
If you want to count Nulls separately for multiple fields in a single query, you can do something like this:
SELECT
Sum(IIf(some_field Is Null, 1, 0)) AS NullsIn_some_field,
Sum(IIf(another_field Is Null, 1, 0)) AS NullsIn_another_field
FROM MyTable;
If you want a grand total of all Nulls, instead of a count per column, you can use the previous query as a subquery and add up the individual column counts.
SELECT base.NullsIn_some_field + base.NullsIn_another_field AS total_nulls
FROM
(
SELECT
Sum(IIf(some_field Is Null, 1, 0)) AS NullsIn_some_field,
Sum(IIf(another_field Is Null, 1, 0)) AS NullsIn_another_field
FROM MyTable
) AS base;
OTOH, if you prefer to avoid SQL altogether, or simply find those statements too complex, you don't need to use SQL. You could use the DCount() function in a VBA procedure.
Run the procedure below in the Immediate window with the name of a table in your database:
HowManyNulls "YourTable"
You can go to the Immediate window with the CTRL+g keyboard shortcut.
Public Sub HowManyNulls(ByVal pTable As String)
Dim db As DAO.Database
Dim fld As DAO.Field
Dim tdf As DAO.TableDef
Dim lngNulls As Long
Dim lngTotal As Long
Set db = CurrentDb
Set tdf = db.TableDefs(pTable)
For Each fld In tdf.Fields
'lngNulls = DCount("*", pTable, fld.Name & " Is Null")
' accommodate field names which need bracketing ...
lngNulls = DCount("*", pTable, "[" & fld.Name & "] Is Null")
lngTotal = lngTotal + lngNulls
Debug.Print fld.Name, lngNulls
Next fld
Debug.Print "Grand total", lngTotal
Set fld = Nothing
Set tdf = Nothing
Set db = Nothing
End Sub
If none of these suggestions is satisfactory, please revise your question to help us better understand what you need.
There is no easy way to perform this kind of count across "all columns" of a table when you do not know the column names in advance.
If you want to do so, you have to write a program to read the "metadata" of the database, extract a list of columns and tables from that data, for each column build a separate SQL statement, then execute that statement and add the number you get back to a running total of NULL values found.
Does this sound like something you might consider pursuing? If so, you should search for solutions on getting the list of tables in an MS Access database and getting the list of columns for a table in an Access database, and then combine that information with the information you already have from the question about counting NULLs in a column.
To count null values in a table of all columns:
select count(*) from(select a from tt where a is null
union all
select b from tt where b is null
union all
select c from tt where c is null)