Я добавил некоторые изменения в код из этого ответа ( https://stackoverflow.com/a/24588210/4489664 ), потому что для nullable Types он вернет исключение
public static List DataTableToList(this DataTable table) where T: new()
{
List list = new List();
var typeProperties = typeof(T).GetProperties().Select(propertyInfo => new
{
PropertyInfo = propertyInfo,
Type = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType
}).ToList();
foreach (var row in table.Rows.Cast())
{
T obj = new T();
foreach (var typeProperty in typeProperties)
{
object value = row[typeProperty.PropertyInfo.Name];
object safeValue = value == null || DBNull.Value.Equals(value)
? null
: Convert.ChangeType(value, typeProperty.Type);
typeProperty.PropertyInfo.SetValue(obj, safeValue, null);
}
list.Add(obj);
}
return list;
}
Вам не нужен префикс таблицы в вашем SELECT из таблицы SQL. Просто сделайте SELECT * FROM dbo_SQLServerTable;
. Лучше всего не использовать SELECT *
, а указывать столбцы на случай, если схемы таблиц изменятся.
dbo_SQLServerTable - это имя таблицы Access, а не имя таблицы SQL-сервера. Поскольку вы уже создали связанную таблицу dbo_SQLServerTable, вы можете использовать следующий код VBA.
Currentproject.connection.execute "INSERT INTO MyAccessTable(fld1, fld2, fld3) SELECT fld1, fld2,fld3 FROM dbo_SQLServerTable"
Нет необходимости создавать объект соединения в коде VBA. Currentproject.connection всегда доступен для ссылки.
Есть несколько предложений по этой конкретной проблеме.
Наименьшее количество кода, которое я могу придумать, - это использовать сквозной запрос.
Установите запрос PT к рассматриваемой базе данных сервера.
Тогда ваш код для создания новой таблицы в доступе будет выглядеть следующим образом:
Sub TestImport()
Dim strSQL As String
With CurrentDb.QueryDefs("qryPassR")
.SQL = "select * from tblHotels"
End With
Dim strLocalTable As String
strLocalTable = "zoo"
CurrentDb.Execute "select * into " & strLocalTable & " FROM qryPassR"
End Sub
Выше, конечно, предполагается, что вы создали соединение с сервером sql (одна база данных) при создании запроса PT. Приведенный выше подход хорош, поскольку вы не возитесь со строками соединения в коде.
Однако, учитывая, что вам нужно (хотите) указать базу данных (и, скорее всего, сервер), выше приведено следующее:
Sub TestImport2()
Dim strSQL As String
Dim strServer As String
Dim strDatabase As String
Dim strUser As String
Dim strPass As String
strServer = ""
strDatabse = ""
strUser = ""
strPass = ""
Dim strLocalTable As String
Dim strServerTable As String
With CurrentDb.QueryDefs("qryPassR")
.Connect = dbCon(strServer, strDatabase, strUser, strPass)
.SQL = "select * from " & strServerAble
End With
CurrentDb.Execute "select * into " & strLocalTable & " FROM qryPassR"
End Sub
Выше используется «удобная» функция для создания строки подключения.
Эта функция выглядит следующим образом:
Public Function dbCon(ServerName As String, _
DataBaseName As String, _
Optional UserID As String = "", _
Optional USERpw As String, _
Optional APP As String = "Office 2010", _
Optional WSID As String = "Import") As String
' returns a SQL server conneciton string
dbCon = "ODBC;DRIVER=" & SQLDRIVER & ";" & _
"SERVER=" & ServerName & ";" & _
"DATABASE=" & DataBaseName & ";"
If UserID <> "" Then
dbCon = dbCon & "UID=" & UserID & ";" & "PWD=" & USERpw & ";"
End If
dbCon = dbCon & _
"APP=" & APP & ";" & _
"WSID=" & WSID & ";" & _
"Network=DBMSSOCN"
End Function
Плакат запросил решение для добавления данных в СУЩЕСТВУЮЩУЮ таблицу.
В этом случае просто измените это:
CurrentDb.Execute "select * into " & strLocalTable & " FROM qryPassR"
на
CurrentDb.Execute "INSERT INTO " & strLocalTable & " SELECT * FROM qeryPassR"