2016-10-18 6 views
2

Я работаю с таблицей с большим количеством полей (40+), в которой каждая запись имеет некоторые поля, которые необходимо заполнить «пользовательскими» данными (на основе по результатам программы), а остальным нужны одинаковые значения «по умолчанию», введенные повторно. Я пишу эту программу в VBA через MS-доступ.Эффективное заполнение большого количества полей в SQL/VBA

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

Мой текущий код

DoCmd.RunSQL "INSERT INTO Table1 ([PartNumber],[Description],[Alternate],[Supplier],[Location],[Rev]) values('" & PartNumber & "','" & Description & "'," _ 
           & " '" & Alt & "', '" & Supplier & "', '" & Location & "','" & Rev & "')" 

Так что это собирается получить некрасиво с большим количеством 35+ значений.

+0

Создание переменных с соответствующим значением для каждого поля в первую очередь. Используйте эти переменные в своем запросе на вставку. Используйте параметры запроса. –

+0

Что вы подразумеваете под "Query Parameters"? Переменные в запросе вставки, уже заданные до выполнения вышеприведенного кода, - это просто вставка переменных в поля, которые кажутся мне уродливыми. – user2059972

ответ

1

Я также искал ответ аналогичной проблемы, зная, что вставка, подобная вашему примеру, действительно сумасшедшая (и уродливая) идея. То, что я придумал было что-то вроде этого:

Option Explicit 

Public Sub GenerateDataIntoTable() 

    Dim str_table_name  As String: str_table_name = "Main" 
    Dim arr_column_names As Variant 
    Dim arr_values   As Variant 

    ReDim arr_column_names(6) 
    ReDim arr_values(6) 

    arr_column_names(0) = "UserName" 
    arr_column_names(1) = "CurrentDate" 
    arr_column_names(2) = "CurrentTime" 
    arr_column_names(3) = "CurrentLocation" 
    arr_column_names(4) = "Status1" 
    arr_column_names(5) = "Status2" 
    arr_column_names(6) = "Status3" 

    arr_values(0) = Environ("username") 
    arr_values(1) = Date 
    arr_values(2) = Time 
    arr_values(3) = Application.ActiveWorkbook.FullName 
    arr_values(4) = 2 
    arr_values(5) = arr_values(4) + 4 
    arr_values(6) = arr_values(5) - 4 

    Debug.Print b_insert_into_table(str_table_name, arr_column_names, arr_values) 

End Sub 

Function b_insert_into_table(str_table_name As String, arr_column_names As Variant, arr_values As Variant) As Boolean 

    Dim conn   As Object 
    Dim str_order  As String 

    Set conn = CreateObject("ADODB.Connection") 
    'conn.Open str_connection_string 

    str_order = "insert into dbo." & str_table_name 
    str_order = str_order & str_generate_order(arr_column_names, arr_values) 
    Debug.Print str_order 
    'conn.Execute str_order 
    'conn.Close 
    Set conn = Nothing 

    b_insert_into_table = True 

End Function 

Public Function str_generate_order(arr_column_names As Variant, arr_values As Variant) As String 

    Dim l_counter  As Long 
    Dim str_result  As String 

    Dim str_left  As String: str_left = "('" 
    Dim str_midd  As String: str_midd = "','" 
    Dim str_right  As String: str_right = "')" 

    str_result = "(" 
    For l_counter = LBound(arr_column_names) To UBound(arr_column_names) 
     str_result = str_result & arr_column_names(l_counter) & "," 
    Next l_counter 

    str_result = Left(str_result, Len(str_result) - 1) 
    str_result = str_result & ")" 
    str_result = str_result & "values" 

    str_result = str_result & str_left 
    For l_counter = LBound(arr_values) To UBound(arr_values) 
     str_result = str_result & arr_values(l_counter) 

     If l_counter < UBound(arr_values) Then 
      str_result = str_result & str_midd 
     Else 
      str_result = str_result & str_right 
     End If 

    Next l_counter 

    str_generate_order = str_result 

End Function 

Для того, чтобы запустить его, запустить GenerateDataIntoTable(). Если вы хотите запустить его в приложении, раскомментируйте комментарии в b_insert_into_table и установите что-то значимое для str_connection_string.

Я не уверен, является ли это хорошая идея, чтобы дать ссылки на мой GitHub репо (это можно считать своего рода рекламой или и т.д.), но вот некоторые похожие проекты:

https://github.com/Vitosh/VBA_personal/tree/master/SQL%20VBA

Если вы думаете, что что-то можно улучшить (например, мы можем добавить два массива в качестве параметров для GenerateDataIntoTable), не стесняйтесь, дайте мне знать.

0

Рассмотрите параметризованный запрос, который является лучшей практикой в ​​индустрии программирования во всех RDMS, где вы готовите исходный оператор SQL, а затем связываете значения с объявленными параметрами в соответствии с их типами данных. Таким образом, вы избегаете включения каждого значения с необходимыми кавычками и можете даже выполнять итерацию без повторного назначения запроса. И самое главное, вы преодолеваете sql injection, поскольку злонамеренные пользователи могут запускать SQL-запросы с помощью ввода пользователем и наносить серьезный вред данным и/или схеме.

В MS Access SQL вы можете использовать предложение PARAMETERS для определения именованных параметров. Затем в VBA вы можете назначать значения для каждого. Также с сохраненным запросом обработка более эффективна, так как ваш запрос оптимизируется движком в сравнении с строковым запросом VBA, обработанным как новый запрос во время выполнения.

SQL(за исключением ниже в качестве сохраненного запроса, добавьте все 40 полей)

PARAMETERS partparam INTEGER, descparam TEXT(255), altparam TEXT(255), 
      supplierparam TEXT(255), locationparam TEXT(255), revparam TEXT(255); 
INSERT INTO Table1 ([PartNumber],[Description],[Alternate], [Supplier],[Location],[Rev]) 
VALUES(partparam, descparam, altparam, supplierparam, locationparam, revparam); 

VBA(эталонные хранится QueryDef и связывания значения с соответствующими именами Params)

Dim db as Database 
Dim qdef as Querydef 

Set db = CurrentDb  
Set qdef = db.QueryDefs("SavedQueryName") 

qdef!partparam = 9999 
qdef!descparam = "Some description" 
qdef!altparam = "Some alternate" 
qdef!supplierparam = "Some supplier" 
qdef!locationparam = "Some location" 
qdef!revparam = "Some rev" 

qdef.Execute dbFailOnError 

Set qdef = Nothing 
Set db = Nothing 
0

Сделайте это как Parfait. Это бесконечно легче поддерживать, отлаживать и т. Д. Также см. Образец ниже.

Sub ADOFromExcelToAccess() 
' exports data from the active worksheet to a table in an Access database 
' this procedure must be edited before use 
Dim cn As ADODB.Connection, rs As ADODB.Recordset, r As Long 
    ' connect to the Access database 
    Set cn = New ADODB.Connection 
    cn.Open "Provider=Microsoft.Jet.OLEDB.4.0; " & _ 
     "Data Source=C:\FolderName\DataBaseName.mdb;" 
    ' open a recordset 
    Set rs = New ADODB.Recordset 
    rs.Open "TableName", cn, adOpenKeyset, adLockOptimistic, adCmdTable 
    ' all records in a table 
    r = 3 ' the start row in the worksheet 
    Do While Len(Range("A" & r).Formula) > 0 
    ' repeat until first empty cell in column A 
     With rs 
      .AddNew ' create a new record 
      ' add values to each field in the record 
      .Fields("FieldName1") = Range("A" & r).Value 
      .Fields("FieldName2") = Range("B" & r).Value 
      .Fields("FieldNameN") = Range("C" & r).Value 
      ' add more fields if necessary... 
      .Update ' stores the new record 
     End With 
     r = r + 1 ' next row 
    Loop 
    rs.Close 
    Set rs = Nothing 
    cn.Close 
    Set cn = Nothing 
End Sub 

http://www.erlandsendata.no/english/index.php?d=envbadacexportado

ИЛИ. , ,

Sub DAOFromExcelToAccess() 
' exports data from the active worksheet to a table in an Access database 
' this procedure must be edited before use 
Dim db As Database, rs As Recordset, r As Long 
    Set db = OpenDatabase("C:\FolderName\DataBaseName.mdb") 
    ' open the database 
    Set rs = db.OpenRecordset("TableName", dbOpenTable) 
    ' get all records in a table 
    r = 3 ' the start row in the worksheet 
    Do While Len(Range("A" & r).Formula) > 0 
    ' repeat until first empty cell in column A 
     With rs 
      .AddNew ' create a new record 
      ' add values to each field in the record 
      .Fields("FieldName1") = Range("A" & r).Value 
      .Fields("FieldName2") = Range("B" & r).Value 
      .Fields("FieldNameN") = Range("C" & r).Value 
      ' add more fields if necessary... 
      .Update ' stores the new record 
     End With 
     r = r + 1 ' next row 
    Loop 
    rs.Close 
    Set rs = Nothing 
    db.Close 
    Set db = Nothing 
End Sub 

http://www.erlandsendata.no/english/index.php?d=envbadacexportdao

Смежные вопросы