Пока Loop в VBA Access - PullRequest
       2

Пока Loop в VBA Access

0 голосов
/ 29 октября 2018

У меня есть функции удаления и добавления, которые строят Таблицу 1 на основе входных данных пользователя. Поэтому для таблицы Table1 для каждого пользователя добавляется разное количество записей.

Мой SQL-код работает для поиска дат, но он делает это только один раз, мне нужно зациклить SQL-код по длине таблицы. Я не очень хорош в кодировании, я попробовал оператор while, не уверен, смогу ли я использовать переменную Z в критериях для этого, но я хочу, чтобы он работал до тех пор, пока не будет заполнен due_date в записи с наименьшим значением ID.

Вот что я попробовал:

Private Sub Command7_Click()
Y = DMax("ID", "Table1", BuildCriteria("Due_date", dbDate, "Null"))
A = DMin("ID", "Table1", BuildCriteria("Due_date", dbDate, "Not Null"))
X = DMin("ID", "Table1")
Z = DLookup("Due_date", "Table1", BuildCriteria("ID", dbLong, CStr(X)))

B = DLookup("Duration", "Table1", BuildCriteria("ID", dbLong, CStr(Y)))
C = DLookup("Due_date", "Table1", BuildCriteria("ID", dbLong, CStr(A)))
E = DateAdd("d", -B, C)

Dim SQL As String

SQL = "UPDATE Table1 " & _
    "SET " & BuildCriteria("Due_date", dbDate, CStr(E)) & " " & _
    "WHERE " & BuildCriteria("ID", dbLong, CStr(Y))


While Z Is Null
DoCmd.RunSQL SQL

End While

End Sub

Для иллюстрации:

  • Перед запуском SQL

    Before Running SQL

  • После запуска SQL один раз

    After running SQL once

  • После нескольких нажатий

    After clicking several times

Цель состоит в том, чтобы щелкнуть один раз, и вся таблица заполняется

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Предположим, что на самом деле нет цикла For, нет BuildCriteria и даже нет VBA SQL. Сохраните запрос на обновление как объект запроса действия MS Access, который запускается по нажатию кнопки.

В частности, вам потребуется несколько функций домена - DLookUp, DSum и DMax - где вы вычисляете текущую сумму дней продолжительности (т. Е. Коррелированное совокупное вычисление), а затем DateAdd результат для DueDate соответствующего максимума ID без пропусков DueDate .

SQL

UPDATE myTable d
SET d.DueDate =  DateAdd("d", -1 * DSum("Duration", "DueDateDuration", "ID >= " & d.ID),  
                                         DLookUp("DueDate", "DueDateDuration", "ID = " &  
                                                 DMax("ID", "DueDateDuration", "DueDate IS NOT NULL") 
                                       )
                        )
WHERE d.DueDate IS NULL;

* 1022 VBA *

Private Sub Command7_Click()
    DoCmd.OpenQuery "mySavedUpdateQuery"     ' WITH WARNINGS

    CurrentDb.Execute "mySavedUpdateQuery"   ' WITHOUT WARNINGS
End Sub

Для демонстрации на данных выборки:

Перед обновлением (mytable)

ID      Item       Duration     DueDate
2674    Issue             1   2/18/2019
2675    Shipping          1   2/19/2019
2678    Completed         0   2/20/2019
2679    Issue             1 
2680    Shipping         10 
2681    Other             6 
2682    Buy Off           6 
2683    Punch List        3 
2684    Completed         0   3/29/2019

После обновления (mytable)

ID      Item       Duration     DueDate
2674    Issue             1   2/18/2019
2675    Shipping          1   2/19/2019
2678    Completed         0   2/20/2019
2679    Issue             1    3/3/2019
2680    Shipping         10    3/4/2019
2681    Other             6   3/14/2019
2682    Buy Off           6   3/20/2019
2683    Punch List        3   3/26/2019
2684    Completed         0   3/29/2019
0 голосов
/ 29 октября 2018

Ваша переменная Z содержит результат , возвращаемый функцией DLookup при оценке в качестве четвертой строки определения вашего суб Command7_Click; значение этой переменной не изменится, если переменная не будет переопределена.

Цель вашего кода несколько затруднена использованием вашей функции BuildCriteria, поэтому трудно посоветовать лучший способ написания кода ...

Редактировать : BuildCriteria для меня новый - спасибо @Andre за указание на это.

Поскольку содержимое вашего оператора SQL является статическим, в цикле не должно быть необходимости, поскольку внутри цикла ничего не меняется - оператор SQL обновит все записи, которые соответствуют вашим критериям, и ничего не будет делать для каждой последующей итерации ( если только значение, к которому вы обновляете записи, также не удовлетворяет критериям выбора).


EDIT

Исходя из ваших дополнительных объяснений и снимков экрана, вы можете подойти к задаче, перебирая набор записей, отсортированный по полю ID, и последовательно вычисляя соответствующее Due_date для каждой записи - что-то вроде:

Private Sub Command7_Click()
    Dim dbs As DAO.Database
    Dim rst As DAO.Recordset
    Dim dat As Date
    Set dbs = CurrentDb
    Set rst = dbs.OpenRecordset("select * from Table1 order by ID desc")
    With rst
        If Not .EOF Then
            .MoveFirst
            Do Until .EOF
                If Not IsNull(!Due_date) Then
                    dat = !Due_date
                Else
                    dat = DateAdd("d", -!Duration, dat)
                    .Edit
                    !Due_date = dat
                    .Update
                End If
                .MoveNext
            Loop
        End If
        .Close
    End With
    Set rst = Nothing
    Set dbs = Nothing
End Sub

Хотя на основе ваших скриншотов, похоже, что вы пытаетесь использовать Access как электронную таблицу Excel.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...