Expand Range of Numbers in SQL [closed] - ms-access

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Is there an SQL code that can be written to expand these cluster of numbers in the Destination Zip Range column?
Screenshot is attached below
Using Access 2016, thanks

You will need DAO to run this.
Create a helper function to split the zip codes:
Public Function ExpandCluster(ByVal ClusterList As String) As Variant
Dim Clusters As Variant
Dim Items As Variant
Dim ZipCodes() As String
Dim Index As Integer
Dim FirstCode As Integer
Dim LastCode As Integer
Dim ThisCode As Integer
Dim Redimmed As Boolean
Clusters = Split(ClusterList, ",")
ReDim ZipCodes(0)
For Index = LBound(Clusters) To UBound(Clusters)
Items = Split(Clusters(Index), "-")
FirstCode = Val(Items(LBound(Items)))
LastCode = Val(Items(UBound(Items)))
While FirstCode <= LastCode
Debug.Print Index, FirstCode
If Redimmed Then
ReDim Preserve ZipCodes(UBound(ZipCodes) + 1)
Else
Redimmed = True
End If
ZipCodes(UBound(ZipCodes)) = Format(FirstCode, "000")
FirstCode = FirstCode + 1
Wend
Next
ExpandCluster = ZipCodes
End Function
Then use this in a function where you create a record for each zip code extracted with that function:
Public Sub FillTable()
Dim Source As DAO.Recordset
Dim Target As DAO.Recordset
Dim ZipCodes() As String
Dim Index As Integer
Set Source = CurrentDb.OpenRecordset("Select * From tblParent Where ZipRange Is Not Null")
Set Target = CurrentDb.OpenRecordset("Select * From tblChild")
While Not Source.EOF
ZipCodes = ExpandCluster(Source!ZipRange.Value)
For Index = LBound(ZipCodes) To UBound(ZipCodes)
Target.AddNew
' Assign foreign key.
Target!FK.Value = Source!Id.Value
' Assign this zip code.
Target!ZipCode.Value = ZipCodes(Index)
'
' Insert lines for other field values.
'
Target.Update
Next
Source.MoveNext
Wend
Source.Close
Target.Close
End Sub
Some generic names are used. Of course, adjust these to your actual table and field names.

Related

Update 1 in 4 boolean fields in a single table

I have a badly designed table containing 4 boolean fields, and only one of these 4 fields needs to be true.
ATM i'm just trying to generate random data for testing, but I'm unable to find a way to randomly set one of the four fields to true for 10000 rows.
Is there any pure SQL way to this or should I use some VBA code to do this?
The database I have to use is Microsoft Access.
Thanks for your help!
EDIT - based on Hmax's answer
Private Sub UpdateRandomColumns_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rdm As Integer
Dim tab(1 To 4) As String
Set db = CurrentDb
Set rs = db.OpenRecordset("Data")
'4 columns that need to randomly be updated per row
tab(1) = "TimeOut"
tab(2) = "Interaction"
tab(3) = "Responses"
tab(4) = "Manual"
rs.MoveFirst
Do Until rs.EOF
rs.Edit
rdm = Int((4 - 1 + 1) * Rnd + 1)
rs(aray(rdm)) = True
rs.Update
rs.MoveNext
Loop
MsgBox("Update successful")
End Sub
You can use in your UPDATE SQL a VBA function like this:
Public Function Random1of4(varID As Variant, intIndex As Integer) As Boolean
Static curID As Variant
Static intVal As Integer
If curID <> varID Then
'new id, generate new random number from 1 to 4
intVal = Int(Rnd * 4 + 1)
curID = varID
End If
Random1of4 = intIndex = intVal
End Function
This function uses static variables, which keep values between function calls. It internally generates new random number from 1 to 4 (intVal) and returns True if intIndex parameter is equal to intVal. New intVal generated if parameter varID changed.
Create this function in standard module, then create and run UPDATE statement with this function - pass to varID any value from table, which is different for every row (normally primary key) and to intIndex a number from 1 to 4 for each of boolean fields:
UPDATE Data
SET TimeOut = Random1of4([ID], 1)
,Interaction = Random1of4([ID], 2)
,Responses = Random1of4([ID], 3)
,Manual = Random1of4([ID], 4);

Check array for unique values and output csv

I need to loop through an Access query, find all the unique values from a field (in this case called UtilityDunsNumber), put them into an array and then run another query for each DunsNumber in that array and output a CSV file with all the records from that new query, then loop back through to create a file for each DunsNumber.
Here's the code I have thus far:
Private Sub Command0_Click()
Dim db As DAO.Database
Dim records() As DAO.Recordset
Dim duns() As String
Dim i As Integer
Dim fs As String
fs = "C:\TestECI\IN_572_COMPANY_" & Format(Now(), "yyyymmdd") & "_814EN01_"
Set records = db.OpenRecordset("SELECT * FROM qry_RequestECI")
'loop through records, get list of unique DUNS numbers
'get unique duns
For Each Record In records
If IsInArray(Record.UtilityDunsNumber, duns) Then
continue
Else
ReDim Preserve duns(1 To UBound(duns) + 1) As String
' add value on the end of the array
arr(UBound(arr)) = Record.UtilityDunsNumber
End If
Next
For Each UtilityDunsNumber In duns
Set records = db.OpenRecordset("SELECT * FROM qry_RequestECI WHERE UtilityDunsNumber =" & dun)
i = 2000
fs = fs & i & ".csv"
DoCmd.TransferText acExportDelim, , records, fs, True
i = i + 1
Next
End Sub
It is failing here:
Set records = db.OpenRecordset("SELECT * FROM qry_RequestECI")
with the error
"Can't assign to array"
Dim records() As DAO.Recordset
Here you're declaring an array of recordsets...
Dim records As DAO.Recordset
Is probably what you want.
There's a simplification that may or may not help. To get the list of Duns numbers, you can use
set DunsRS=db.openrecordset "select UtilityDunsNumber from qry_RequestECI group by UtilityDunsNumber"
And then you can loop through the list with
DunsRS.movefirst
do while not DunsRS.eof
dun = DunsRS.fields("UtilityDunsNumber").value
...
...
DunsRS.movenext
Loop
This might be enough to fix the problem - not sure without trying it.

Is there a way to conditionally list field names on an access form?

I have a large database that monitors employees attendance at training events. Each record is an employee, and there are (along with basic information) a hundred or so fields that represent training events over the last 10 years. These fields are all yes/no checkboxes and so are checked if the employee attended that workshop.
I have a form that allows viewing information for individual employees easily, but I want a dynamic list on this form that shows what events the currently selected employee attended.
So I want a list to see which fields are designated as true for the specified record.
Is there any way to do this? Been searching all day and can't find a solution. Thanks.
Maybe somthing like this, assuming that all boolean fields are relevant and field name is workshop name:
Public Function getWorkshops(ByVal strEmployee As String) as String
' Declare vars
Dim db as DAO.Database
Dim rs as DAO.Recordset
Dim lngFieldsCount as Long
Dim n as Long
Dim strWorkshops as string
Set db = CurrentDb() '
lngFieldsCount = db.TableDefs("myTable").Fields.Count ' Count number of fields to iterate through
Set rs = db.OpenRecordset("SELECT * FROM myTable WHERE employeeName LIKE '" & strEmployee & "';",DbOpenSnapshot)
Do While not rs.Eof
For n = 0 to lngFieldsCount -1 ' iterate through all fields
If TypeOf rs.Fields(n) is dbBoolean Then ' check if field is boolean
If rs.Fields(n) Then ' check if boolean is true
strWorkshops = strWorkshops & rs.Fields(n).Name & vbCrLf ' add field names to string, separated by linebreaks
End If
End If
Next n
rs.MoveNext
Loop
getWorkshops = strWorkshops 'Set result of function
'Clean up
rs.Close
Set rs = Nothing
Set db = Nothing
End Function
This returns the name of all true fields in a string, separated with linebreaks (not tested).

MS Access compare a value to a table column and return a field from the same row

Ok so i have a complex reason field from one of our logging servers, and i need to break it down to make some sense, problem is the format changes depending on the status.
I managed to find some strings that i can compare the the reason to to get some sense out of it, but I want to distill it down to one reason code.
I scratched my head a bit and got it down to 7 reasons with different criterion, put the criteria in a table and came up with some vb code to do the comparison.
Problem is its dead slow, and half the reporting relies on the Reason code. The basic VBA function is below, This basically loads the criteria into an array and then compares the value against the array to return the ID.
Function Reason_code(LongReason As String) As Integer
Dim NoReason As Integer
Dim I As Integer
Dim J As Integer
Dim x As Boolean
NoReason = recordCount("RejReason") - 1
Dim conExpr() As String
ReDim conExpr(NoReason)
For I = 0 To (NoReason - 1)
conExpr(I) = GetVal("Criterior", "RejReason", "id", CStr(I + 1))
Next I
For J = 0 To (NoReason - 1)
x = LongReason Like conExpr(J)
If x = True Then
GoTo OutOfLoop
End If
Next J
OutOfLoop:
Reason_code = J + 1
End Function
I have used similar in VB before and it tends to be quite fast, so i am reconing that my GetVal function is the problem, but my VBA is rusty and my SQL is pretty non existent, so any help would be appreciated. I tried LSQL and SQL2 as one line but VBA doesnt like it.
Function GetVal(FieldNm As String, TableNm As String, IndexField As String, IndexNo As String) As String
Dim db As Database
Dim Lrs As DAO.Recordset
Dim LSQL As String
Dim LGST As String
Dim SQL2 As String
'Open connection to current Access database
Set db = CurrentDb()
'Create SQL statement to retrieve value from GST table
LSQL = CStr("SELECT " + FieldNm + " FROM " + TableNm)
SQL2 = CStr(LSQL + " WHERE " + IndexField + " = " + IndexNo)
Set Lrs = db.OpenRecordset(SQL2, dbOpenDynaset, dbReadOnly)
'Retrieve value if data is found
If Lrs.EOF = False Then
LGST = Lrs(0)
Else
LGST = "Item Not found"
End If
Lrs.Close
Set Lrs = Nothing
GetVal = LGST
End Function
Thanks in advance,
I Scratched my head for a bit and worked out i could speed it up by doing the read and compare at the same time, its not lightning, but its better
Function ReasonCode(LongReason As String) As String
Dim cdb As Database
Dim rs As DAO.Recordset
Dim RejRea()
Dim NoReason As Integer
Dim result As Boolean
Dim i As Integer
Set cdb = CurrentDb()
Set rs = cdb.OpenRecordset("RejReason", dbOpenDynaset, dbReadOnly)
rs.MoveLast
rs.MoveFirst
NoReason = rs.recordCount - 1
RejRea() = rs.GetRows(rs.recordCount)
For i = 0 To NoReason
result = LongReason Like CStr(RejRea(2, i))
If result = True Then
ReasonCode = CStr(RejRea(1, i))
GoTo outloop
End If
Next i
If ReasonCode = "" Then ReasonCode = "Not Found"
outloop:
Set rs = Nothing
Set cdb = Nothing
End Function
Still not sure its the best way to do it, but in the abscence of any other suggestions it will do for now.

how to reference array variable in vba access to another variable

hi guys im trying to take the value of data(0)
and put it into say variable InvoiceNumber. I tried putting an image of my watch screen but i ended up not being allow. but here is what my watch screen would look like.
data
data(0)
data(0,1) 1
data(0,2) 2
data(0,3) 3
I have tried
dim InvoiceNumber as variant <br/>
invoiceNumber = data(0)
but i keep getting error. I dont know how to reference just the part of that array. any help would be greatly appreciated.
here is the full code for anyone that would like to see a little more.
Dim db As Database
Dim rs As Recordset
Dim data As Variant
Dim colummn1 As Variant
Dim obj As Object
Set db = CurrentDb
Set rs = db.OpenRecordset("select * from Table1")
'set obj = new object
While Not rs.EOF
'MsgBox (rs.RecordCount)
'MsgBox (rs.Fields.Count)
data = rs.GetRows(rs.Fields.Count)
Column1 = data.data(0)
Wend
rs.Close
db.Close
End Sub
Try
Column1 = data(0,0)
instead of
Column1 = data.data(0)
data contains a two-dimensional array. The fist index is the field number, the second index is the row number. Both start at zero. So data(0,0) is the first field of the first row. data(1,0) is the second field of the first row.
I would try to make an array of invoices by using a user defined type
Public Type Invoice
Nr As Variant
IssueDate As Variant
Total As Variant
'Or whatever your invoice contains
End Type
Public Sub TestGetRecords()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim data As Variant
Dim numRecords As Long, i As Long
Dim Invoices() As Invoice
Set db = CurrentDb
Set rs = db.OpenRecordset("select * from Table1")
data = rs.GetRows()
rs.Close
db.Close
numRecords = UBound(data, 2) + 1
ReDim Invoices(0 To numRecords - 1) As Invoice
For i = 0 To numRecords - 1
Invoices(i).Nr = data(0, i)
Invoices(i).IssueDate = data(1, i)
Invoices(i).Total = data(2, i)
Next i
Debug.Print Invoices(0).Total
End Sub
An error in you solution is, that you placed GetRows in a loop. However, GetRows returns all the rows at once!
I am finding it a little hard to understand what you are trying to achieve.
You are reading an entire table of data into a recordset object, loading the fields of the recordset object into a two dimensional array and then trying to iterate through the array to output the results to a single variable (or a sum of array values).
Why don't you just use an SQL expression to extract the data directly from your table?
If we can assume you have a table of invoices (say ... "myInvoiceTable") with at least the following fields ...
invoiceID
invoiceValue
(and probably many others, eg. invoiceDate, clientID, etc.)
you can write an expression something like this
"SELECT SUM(invoiceValue) AS MyTotal FROM myInvoiceTable WHERE invoiceID > xxxx"
This might go into your VBA code like this.
Dim rst as Recordset
Dim strSQL as string
strSQL = "SELECT SUM(invoiceValue) AS MyTotal FROM myInvoiceTable WHERE invoiceID > 400" '-- use an appropriate WHERE clause if needed
Set rst = CurrentDb.Openrecordset(strSQL) '-- the rst object should contain a single value "MyTotal" which is the sum of the fields you are trying to access
MsgBox rst!MyTotal '-- use this value wherever you need to use it