Получение данных за предыдущий финансовый месяц в модуле VBA - PullRequest
1 голос
/ 24 октября 2019

Мой текущий модуль ниже успешно извлекает даты текущего FiscalMonth из моего tbl_calendar. Как мне нужно изменить этот код, чтобы найти даты, которые были получены для предыдущего финансового месяца?

 Function getDates(Optional forDate As String = "1/31/1999") As String 
  Dim rst As Recordset
  getDateRange = vbNullString


If forDate = "1/31/1999" Then

   forDate = DateAdd("d", -1, Date)
End If

If DatePart("d", DateAdd("d", 1, forDate)) = 1 Then
  eom = True
End If

Set rst = CurrentDb.OpenRecordset("SELECT Day, FiscalMonth, FiscalYear 
from tbl_Calendar where FiscalYear = (SELECT FIscalYear from tbl_Calendar 
where day = #" & _
Format(forDate, "Short Date") & "#) and FiscalMonth = (SELECT FiscalMonth 
from tbl_Calendar where day = #" & _
Format(forDate, "Short Date") & "#)")


If rst.EOF Then Exit Function
 rst.MoveLast
 rst.MoveFirst
 getDates = CStr(rst.Fields("day").Value) & ";"
 rst.MoveLast
If DateDiff("d", rst.Fields("day").Value, forDate) < 0 Then
    eom = "False"
Else
    eom = rst.Fields("FiscalMonth").Value & ", " & 
rst.Fields("FiscalYear").Value
 End If
getDates = getDates & IIf(DateDiff("d", rst.Fields("day").Value, forDate) 
< 0, CStr(forDate), CStr(rst.Fields("day").Value)) & ";" & eom
rst.Close
Set rst = Nothing

End Function

1 Ответ

0 голосов
/ 24 октября 2019

Попробуйте использовать DateSerial для построения фискальной даты, затем вычтите один месяц. Кроме того, рассмотрите возможность переписывания запроса для self join , чтобы избежать подзапросов. Также используйте параметризацию с QueryDefs . запускать SQL в VBA для удобочитаемости и удобства обслуживания без объединения или пунктуации с # вложениями:

SQL

Текущий запрос

SELECT [Day], FiscalMonth, FiscalYear 
FROM tbl_Calendar 
WHERE FiscalYear = (SELECT FiscalYear FROM tbl_Calendar WHERE [Day] = #10/24/2019#)
  AND FiscalMonth = (SELECT FiscalMonth FROM tbl_Calendar WHERE [Day] = #10/24/2019#)

СкорректированоИсходный запрос (удалить подзапросы, указывающие на один и тот же источник)

SELECT c.[Day], c.FiscalMonth, c.FiscalYear 
FROM tbl_Calendar c
INNER JOIN tbl_Calendar c2
  ON c.FiscalYear = c2.FiscalYear 
  AND c.FiscalMonth = c2.FiscalMonth
WHERE c2.[Day] = #10/24/2019#

Скорректированный запрос за последний финансовый месяц (лучше как сохраненный запрос для оптимизации)

PARAMETERS [DateParam] AS Datetime;
SELECT c.[Day], c.FiscalMonth, c.FiscalYear 
FROM tbl_Calendar c
INNER JOIN tbl_Calendar c2
  ON DATESERIAL(c.FiscalYear, c.FiscalMonth, 1) = 
     DATEADD('m', -1, DATESERIAL(c2.FiscalYear, c2.FiscalMonth, 1))
WHERE c2.[Day] = [DateParam]

VBA

Function getDates(Optional forDate As Date = #1/31/1999#) As String 
     Dim qdf As QueryDef, rst As Recordset
     Dim sql As String
     getDateRange = vbNullString

     ' SQL (NO DATA)
     sql = "PARAMETERS [DateParam] AS Datetime;" _
            & " SELECT c.[Day], c.FiscalMonth, c.FiscalYear" _
            & " FROM tbl_Calendar c" _
            & " INNER JOIN tbl_Calendar c2" _
            & "    ON DATESERIAL(c.FiscalYear, c.FiscalMonth, 1) =" _
            & "       DATEADD('m', -1, DATESERIAL(c2.FiscalYear, c.FiscalMonth, 1))" _
            & " WHERE c2.[Day] = [DateParam]" _

     If forDate = DateValue("1/31/1999") Then
          forDate = DateAdd("d", -1, Date)
     End If

     If DatePart("d", DateAdd("d", 1, forDate)) = 1 Then
          eom = True
     End If

     ' CREATE TEMP QUERYDEF AND BIND PARAM
     Set qdf = CurrentDb.CreateQueryDef("", sql)  ' OR  .CreateQueryDef("mySavedQuery") 
     qdf![DateParam] = forDate   

     ' OPEN RECORDSET
     Set rst = qdf.OpenRecordset()
     '... same code as before ...  

     rst.Close: qdf.Close    
     Set rst = Nothing: Set qdf = Nothing
End Function
...