date as name of field not recognized in ms access - sql

I have fields which have as name a the date of delivery, as you can see here:
I have around 75 columns like that. I have a bug when I want to compute the value P1 because it does not find the field. BTW, I have very stranges values for my coefficients T1, T2 (which are dates) and thus A and B which are datediff. There is the code:
Sub vcm_fc()
Dim db As Database, T As Date, longest As Integer, nearest_date As Date, rsb As DAO.Recordset, strsqlb As String
Dim strsqla As String, rsa As Recordset, maturity As Date, T1 As Date, T2 As Date, P1 As Double, P2 As Double
Dim a As Integer, B As Integer, j As Integer, rsc As DAO.Recordset, strqlc As String, settlementbis As String
Dim settlement As String, maturitybis As Date, ym As Integer, ymbis As Integer
Set db = CurrentDb()
T = DateSerial(2020, 8, 15)
nearest_date = DFirst("PricingDate", "fc_historical")
longest = DateDiff("m", nearest_date, T)
db.Execute "CREATE TABLE time_series " _
& "(PricingDate CHAR);"
db.Execute " INSERT INTO time_series " _
& "SELECT PricingDate " _
& "FROM fc_historical " _
& "ORDER BY PricingDate;"
For i = 1 To longest
db.Execute " ALTER TABLE time_series " _
& "ADD COLUMN F_" & i & " Number;"
strsqla = "SELECT PricingDate, F_" & i & " FROM time_series ORDER BY PricingDate"
Set rsa = db.OpenRecordset(strsqla, dbOpenDynaset)
rsa.MoveFirst
rsa.Delete 'delete the first row which is blank when the time series table is created'
rsa.MoveFirst
While (Not rsa.EOF())
rsa.Edit
maturity = DateAdd("m", i, rsa.Fields("PricingDate").Value)
ym = Year(maturity) - 2000
settlement = "1/" & Month(maturity) & "/" & ym
strsqlb = "SELECT Pricingdate, " & settlement & " FROM fc_historical ORDER BY PricingDate;"
Set rsb = db.OpenRecordset(strsqlb, dbOpenDynaset)
rsb.MoveLast
T1 = rsb.Fields("PricingDate").Value
maturitybis = DateAdd("m", i, maturity)
ymbis = Year(maturitybis) - 2000
settlementbis = "1/" & Month(maturitybis) & "/" & ymbis
strsqlc = "SELECT Pricingdate, " & settlementbis & " FROM fc_historical ORDER BY PricingDate;"
Set rsc = db.OpenRecordset(strsqlc, dbOpenDynaset)
rsc.MoveLast
T2 = rsc.Fields("PricingDate").Value
a = DateDiff("d", T1, rsa.Fields("PricingDate").Value)
B = DateDiff("d", rsa.Fields("PricingDate").Value, T2)
P1 = rsb.Fields(settlement).Value
P2 = rsc.Fields(settlementbis).Value
rsa.Fields("F_" & i) = (P1 * B + P2 * a) / (a + B)
rsa.Update
rsa.MoveNext
Wend
Next i
End Sub

Have added as an answer so I can get the format for the code. This code will take your date field names and place them as record values - you may need to muck around with the fld.Name to make sure it isn't US date format (8th Jan, 9th Jan, etc for your table example) along with the price for that date.
Sub Put_Field_Names_As_Record_Values()
Dim DB As DAO.Database
Dim OldTable As DAO.TableDef
Dim fld As DAO.Field
Set DB = CurrentDb()
Set OldTable = DB.TableDefs("time_series")
DoCmd.SetWarnings False
For Each fld In OldTable.Fields
If IsDate(fld.Name) Then
Debug.Print fld.Name & " : " & SQLDate(fld.Name)
DoCmd.RunSQL "INSERT INTO MyNewTable (PricingDate, SettlementDate, Price) " & _
"SELECT PricingDate," & SQLDate(fld.Name) & ", [" & fld.Name & "] FROM time_series"
End If
Next fld
DoCmd.SetWarnings True
End Sub
Function SQLDate(varDate As Variant) As String
'Purpose: Return a delimited string in the date format used natively by JET SQL.
'Argument: A date/time value.
'Note: Returns just the date format if the argument has no time component,
' or a date/time format if it does.
'Author: Allen Browne. allen#allenbrowne.com, June 2006.
If IsDate(varDate) Then
If DateValue(varDate) = varDate Then
SQLDate = Format$(varDate, "\#mm\/dd\/yyyy\#")
Else
SQLDate = Format$(varDate, "\#mm\/dd\/yyyy hh\:nn\:ss\#")
End If
End If
End Function
You can then run queries on the table:
SELECT SUM(Price)
FROM MyNewTable
WHERE PricingDate<=#07/16/2014# AND SettlementDate=#01/08/2014#
Edit: Test on a copy of your database!!
Edit 2: Manually create the MyNewTable and set PricingDate and SettlementDate as key fields.
I've updated to convert the field name into the correct date - http://allenbrowne.com/ser-36.html
On my test it converted all dates to the first of each month correctly.

Use properly formatted date expressions:
settlementbis = "#" & CStr(ymbis) & "/" & CStr(Month(maturitybis)) & "/1#"
And do listen to Darren about normalisation.

Related

VBA ACCESS - SQL statement which Counting between 2 columns which are variables

I need a macro in VBA Access. I have a table with all dates of the years like columns (and also the dates are the names of the fields). I've made a form where the user selects two dates, and the macro would count all the data between these 2 columns.
For the example, I put two fixed dates. The problem is I need count between the 2 columns, and the columns can change depending the input of the user. The table is EVOLUTIVO_ASISTENCIA and the field can change depends the user selection. Ihe following code EVOLUTIVO_ASISTENCIA.[" & INICIO_MES_VAR1 & "] is the field "01-01-2023" of the EVOLUTIVO_ASISTENCIA table, but the syntax is wrong and does not function. Can anyone help me?
The code:
Private Sub BUSQUEDA()
Dim CONTEO As String
Dim VAR1 As String
Dim INICIO_MES_VAR1 As Date, TERMINOS_MES_VAR1 As Date
INICIO_MES_VAR1 = Format("01-01-2023", "dd-mm-yyyy")
TERMINOS_MES_VAR1 = Format("31-01-2023", "dd-mm-yyyy")
VAR1 = "VAR1"
CONTEO = "SELECT COUNT(*) FROM EVOLUTIVO_ASISTENCIA " & _
"WHERE EVOLUTIVO_ASISTENCIA.[NOMBRES]='" & VAR1 & "' " & _
** "BETWEEN EVOLUTIVO_ASISTENCIA.[" & INICIO_MES_VAR1 & "] AND EVOLUTIVO_ASISTENCIA.[" & TERMINOS_MES_VAR1 & "]"**
DoCmd.RunSQL CONTEO
End Sub
You don't run a select query, you open it as a recordset. So try:
Private Sub BUSQUEDA()
Dim Records As DAO.Recordset
Dim CONTEO As String
Dim VAR1 As String
Dim INICIO_MES_VAR1 As String
Dim TERMINOS_MES_VAR1 As String
Dim ASISTENCIA_CONTEO As Long
INICIO_MES_VAR1 = "01-01-2023"
TERMINOS_MES_VAR1 = "31-01-2023"
VAR1 = "VAR1"
CONTEO = "SELECT COUNT(*) FROM EVOLUTIVO_ASISTENCIA " & _
"WHERE EVOLUTIVO_ASISTENCIA.[NOMBRES]='" & VAR1 & "' " & _
"BETWEEN EVOLUTIVO_ASISTENCIA.[" & INICIO_MES_VAR1 & "] AND EVOLUTIVO_ASISTENCIA.[" & TERMINOS_MES_VAR1 & "]"
Set Records = CurrentDb.OpenRecordset(CONTEO)
' Read/list/print records.
' Retrieve the value of the first and only field of the first and only record.
ASISTENCIA_CONTEO = Records(0).Value
' Close when done.
Records.Close
End Sub

Date filter returns an invalid character error

I want to execute a query with a date filter in Access VBA.
My first issue was inconsistent datatypes: expected DATE got NUMBER.
I assume Access stores dates as numbers just like Excel.
I found I had to use "#" between the date for the query to recognize it as a DATE. Now I am getting an INVALID CHARACTER error which means the hash # is an invalid character.
I have to pull in the negotiated costs with our vendors that don't have more than 60 days of being expired.
There is also a tblVendors where the user selects the vendor ID (ORDID) they want to pull the info from. That's why I do a loop to pull in every ORDID in that table. I don't push in all the ORDID in one try because it brings a lot of data and doing it in batches runs faster.
Sub GetMaterialCost()
Dim db As Database
Dim rsData As ADODB.Recordset, rsVendor As DAO.Recordset, rsItemCost As DAO.Recordset
Dim strQuery As String
Dim vendorNO As Long, dtDate As Date
Set db = CurrentDb
dtDate = Format(Now() - 60, "m/d/yyyy")
Set rsVendor = db.OpenRecordset("SELECT ORDID, VEN_NAME, USER_ID FROM tblVendors WHERE ACTIVE = TRUE ORDER BY VEN_NAME, ORDID")
Set rsItemCost = db.OpenRecordset("tbl_ItemCost")
ConnectBILL
rsVendor.MoveFirst
Do Until rsVendor.EOF
strQuery = "SELECT MASID, LOCATION, ITEM, ITEM_QTY, ITEM_UOM, ITEM_COST, EXP_DT " _
& "FROM ITEMMASTER INNER JOIN ORDDETAIL ON (ITEMMASTER.ITEM = ORDDETAIL.ITEM) " _
& "WHERE (LOCATION IN (AS1,AS3,AS6) AND TRIM(MASID) = '" & Cstr(rsVendor.Fields("ORDID")) & "' AND EXP_DT >= #paramDate)"
With ComBill
.CommandText = strQuery
Set rsData = .Execute(, Array(dtDate))
end with
'clears previous instance of vendor data by vendor_no if it exists
db.Execute "DELETE * FROM tbl_ItemCost WHERE MASID LIKE '*" & rsVendor.Fields("ORDID") & "*'"
'starts inserting queried data
rsData.MoveFirst
Do Until rsData.EOF
With rsItemCost
.AddNew
.Fields("MASID") = rsData!MASID
.Fields("LOCATION") = rsData!LOCATION
.Fields("ITEM") = rsData!ITEM
.Fields("ITEM_UOM") = Trim(rsData!ITEM_UOM)
.Fields("ITEM_COST") = rsData!ITEM_COST
.Fields("EXP_DT") = rsData!EXP_DT
.Update
End With
rsData.MoveNext
Loop
rsVendor.MoveNext
Loop
End Sub
Correct these two lines:
dtDate = DateAdd("d", -60, Date)
& "WHERE LOCATION IN (AS1,AS3,AS6) AND TRIM(MASID) = '" & CStr(rsVendor.Fields("ORDID") & "' AND EXP_DT >= #" & Format(dtDate, "yyyy\/mm\/dd") & "#) "
Note, that for ADO, string expressions for date values must be formatted using the ISO sequence.
If the field EXP_DT is Text:
& "WHERE LOCATION IN (AS1,AS3,AS6) AND TRIM(MASID) = '" & CStr(rsVendor.Fields("ORDID") & "' AND EXP_DT >= '" & Format(dtDate, "m\/d\/yyyy") & "') "

SQL Statement to Public Function

I have a query that gives me the Current Employee Rate based on the WorkDay:
(Select Top 1 T1.Rate FROM tblERates as T1
WHERE T1.EMPID = tblPayroll.EMPID And T1.EffectiveDate <= tblPayroll.WorkDay
ORDER BY T1.EMPID asc, T1.EffectiveDate desc)
The project is growing. I need to return the Employee Rate on different Forms/Reports so I want to convert this SQL to a Public Function.
I tried this:
Public Function fncERate(EID As Integer, WD As Date) As Double
Dim intERate As Double
Dim intWD As String
intWD = "#" & Format(WD, "m/d/yyyy") & "#"
intERate = "SELECT TOP 1 Rate" _
& "FROM tblERates" _
& "WHERE EMPID = EID And EffectiveDate <= intWD" _
& "ORDER BY EMPID asc;"
fncERate = intERate
End Function
I get a "type mismatch error".
After tinkering a bit I came up with this:
Public Function fncERate(EID As Integer, WD As Date) As Double
Dim intERate As String
Dim intWD As String
Dim intEID As Integer
intWD = "#" & Format(WD, "m/d/yyyy") & "#"
intERate = "SELECT TOP 1 [Rate]" & _
" FROM tblERates" & _
" WHERE [EMPID] = " & EID & " And [EffectiveDate] <= " & intWD & " " & _
" ORDER BY [EMPID] asc;"
With CurrentDb.OpenRecordset(intERate)
If Not (.BOF And .EOF) Then
fncERate = .Fields(0)
End If
End With
End Function
Yes you lack spaces in your sql syntax
A little tip for quick dev
Press Ctrl+G to open execution pane while debugging and type
?intERate
to print the value of your variable
then you can just copy paste the sql and try it directly

VBA SQL string saving short date as General date instead of short

I'm trying to do something basic:
Take 2 dates [startD] and [endD] from a accdb file.
Move them forward one month each
save the new dates as short dates in the respective record.
I'm doing this all by VBA
The issue is that it is showing the correct SQL String (if i do msgbox sql) however when it saves, it is saving as a general date with time and is the wrong value!
*Note: I'm in Australia so I have a format section to make sure the date saves correctly.
I have tried using DateValue() and Formatting the date too.
Dim frq As Integer
Dim wks As Integer
Dim CurAcc As Integer
Dim CurAccEnd As Date
Dim Days As Integer
Dim curaccvalue As Currency
Dim cardtype As Integer
Dim cardcharged As Integer
cardtype = 0
cardcharged = 0
CurAcc = Me.ID
curraccvalue = DLookup("Acccurvalue", "Accounts", "[ID] = " & CurAcc)
Curraccend = DLookup("Accend", "Accounts", "[ID] = " & CurAcc)
frq = DLookup("freqid", "Accounts", "[ID] = " & CurAcc)
wks = DLookup("freqvalue", "tblfrequency", "FrequencyID = " & frq)
Days = wks * 7
strsql = "UPDATE Accounts SET AccStart = " & Date & " , AccEND = " &
Curraccend + Days & " , AccCurValue = 0.00 WHERE ID = " & CurAcc
MsgBox strsql
DoCmd.RunSQL strsql
When implicitly converting a date to a string, your regional settings are used, but in a SQL string, a date must be in the American format.
To avoid this, I suggest to do the update in just one query:
Dim strSql As String
strSql = "UPDATE Accounts " & _
"INNER JOIN tblfrequency ON Accounts.freqid = tblfrequency.FrequencyID SET " & _
"AccStart = Date(), " & _
"AccEND = DateAdd(""w"", tblfrequency.freqvalue, Accounts.Accend), " & _
"AccCurValue = 0.00 WHERE ID = " & Me.ID
MsgBox strSql
DoCmd.RunSQL strSql

iteration (for-loop) ms Access with past value

I tried to translate a code from VBA excel to access. My data is a column of prices and I want to compute the returns.
This is the original VBA code in excel:
DerCol = Cells(T.Row, Columns.Count).End(xlToLeft).Column
Cells(T.Row, DerCol + 1) = "Returns"
For i = T.Row + 2 To T.End(xlDown).Row
Cells(i, DerCol + 1) = Application.WorksheetFunction.Ln(Cells(i, T.Column)) - Application.WorksheetFunction.Ln(Cells(i - 1, T.Column))
Next i
To get an idea of the output that I have in excel, click here.
In Access, I created a new column next to the prices' column and I would like to fill in exactly like in excel:
Sub vardaily()
Dim db As Database, T As Object, DerCol As Integer, y As TableDef
Dim rs As DAO.Recordset, i As Integer, strsql As String
'idea = SELECT prices FROM dailypricing, then creates newtable "VAR", copy and prices, compute historical and parametric VAR '
'create a new table var_daily'
Set db = CurrentDb()
'insert the pricing date and the prices from dbo_daily'
db.Execute "CREATE TABLE VAR_daily" _
& "(PricingDate CHAR, Price Number);"
'where clause to select the same traded product only'
db.Execute " INSERT INTO VAR_daily " _
& "SELECT PricingDate, Price " _
& "FROM dbo_PricingDaily " _
& "WHERE IndexId = 1;"
db.Execute " ALTER TABLE VAR_daily " _
& "ADD COLUMN Returns Number;"
'sql request to store prices'
strsql = "SELECT First(Price) as FirstPrice, Last(Price) as EndPrice FROM VAR_daily;"
'dao.recordset of the store prices'
Set rs = db.OpenRecordset(strsql, dbOpenDynaset)
'loop to change the prices'
For i = 2 To i = rs.RecordCount
rs.Edit
rs!Price(i) = Log(rs!Price(i)) - Log(rs!Price(i - 1))
rs.Update
Next i
db.Execute "INSERT INTO VAR_daily " _
& "(Returns) VALUES " _
& "(" & rs![Price] & ");"
End Sub
I have the following table that you can see here
I can not manage with the loop. I have no item in my collection at the end.
I looked at other example of loops like here but I did not find how to make an iteration with the last result.
Sorry, I really am a beginner in Ms Access and SQL. I started this week so I apologize if my question is very basic.
EDIT: I added the images and I replaced Firsttransaction and Lasttransaction by "FirstPrice" and "EndPrice".
EDIT2: Thanks to my new privilege, I can share a sample for those who are interested.
I have updated your complete code to what it should be. Again, I don't have an Access database handy to test it but it compiles and should work:
Sub vardaily()
Dim db As Database
Dim rs As DAO.Recordset, i As Integer, strsql As String
Dim thisPrice, lastPrice
'idea = SELECT prices FROM dailypricing, then creates newtable "VAR", copy and prices, compute historical and parametric VAR '
'create a new table var_daily'
Set db = CurrentDb()
'insert the pricing date and the prices from dbo_daily'
db.Execute "CREATE TABLE VAR_daily" _
& "(PricingDate CHAR, Price Number);"
'where clause to select the same traded product only'
db.Execute " INSERT INTO VAR_daily " _
& "SELECT PricingDate, Price " _
& "FROM dbo_PricingDaily " _
& "WHERE IndexId = 1 " _
& "ORDER BY PricingDate;"
db.Execute " ALTER TABLE VAR_daily " _
& "ADD COLUMN Returns Number;"
'sql request to retrieve store prices'
strsql = "SELECT * FROM VAR_daily ORDER BY PricingDate;" ' just get all fields
'dao.recordset of the store prices'
Set rs = db.OpenRecordset(strsql, dbOpenDynaset)
'loop to change the prices'
lastPrice = rs.Fields("Price") ' get price from first record and remember
rs.MoveNext ' advance to second record and start loop
While (Not rs.EOF())
thisPrice = rs.Fields("Price")
rs.Edit
rs!Returns = Log(thisPrice) - Log(lastPrice)
rs.Update
lastPrice = thisPrice ' remember previous value
rs.MoveNext ' advance to next record
Wend
End Sub