Я пытаюсь выполнить запрос на листе Excel, как делал много раз, но теперь данные содержат более 70 тыс. строк. Обычно я получаю сообщение о том, что он не может найти таблицу, если это так, чего и следовало ожидать, поскольку я думаю, что она перестает работать примерно на 65 тыс. строк или около того.
Итак, вместо этого я пытаюсь выполнить цикл, в котором в первой части цикла я запускаю первые 60 000 строк, и на каждой итерации цикла выполняется еще одна партия из 60 000, пока не закончится последний набор. Цикл создает новый лист с данными для работы, поэтому я могу иметь заголовки столбцов с набором данных. Кажется, он работает до той части, где он запускает новый запрос к данным из нового листа. Это дает мне ошибку, что «Ядро базы данных Microsoft Access не может найти объект» (имя моей таблицы)... и т. д.
В моем конкретном примере это таблица «Sheet1$A1:N12790», где 12790 — это остаточное количество строк из более чем 70 тыс. строк, а Sheet1 — это лист, который создается при запуске кода.
Итак, я совершенно не понимаю, почему он выдает эту ошибку, когда обычно это происходит только в том случае, если строк слишком много или таблица определенно не существует.
Я попытался запустить простой Select * from [Sheet1$A1:N12790]
с отдельным сабвуфером, и он отлично работает. Это наводит меня на мысль, что, возможно, у excel не хватает памяти, возможно, после выполнения первого? Но я понятия не имею, что с этим делать, и в Интернете очень мало информации об этом, поскольку это настолько специфично и редко, поскольку большинство людей на данный момент просто используют обычную базу данных.
Спасибо!
ОБНОВЛЕНИЕ: я тестировал много вещей. Я попытался создать тестовый модуль для обработки нового листа (как описано выше), и он работает при отдельном запуске, но если я попытаюсь заставить основной модуль выйти из цикла раньше, а затем вызвать новый тестовый модуль для запуска того, что я хочу это сделать, это дает мне ту же ошибку. Итак, опять же, оба сабвуфера отлично работают по отдельности, но я не могу использовать один для вызова другого. Показывает мне больше доказательств того, что речь идет не столько о кодировании, сколько о каком-то усложнении обработки, но я все еще просто выдвигаю теории.
Обновление 2: Спасибо за все идеи и предложения до сих пор (20.06.18). Вот скриншот того, что говорит ошибка, когда она запускается во второй раз и пытается запустить MySQL:
Сообщение об ошибке:
Вот мой код ниже, если это полезно:
Sub Risk_Init_Pivot(FA_PQ, Risk_Init, SubChannel, MyMonth As String)
Application.ScreenUpdating = False
Dim SheetRange1 As Range, SheetRange2 As Range, SheetRange3 As Range, MyRange As Range
Dim TargetSheetTable As String, SheetTable1 As String
Dim SR1_LastRow As Double, SR1_LastColumn As Double, NewRowCount As Double, SR1_FirstRow As Double
Dim i As Integer, j As Integer, MyLoop As Integer
Dim Table1 As String, MySQL As String
Dim MySheet1 As Worksheet, MySheet2 As Worksheet
Dim MyConn As ADODB.Connection
Dim MyRecordSet As ADODB.Recordset
TargetSheetTable = "Risk Init Pivot"
SheetTable1 = "Fanned File"
'Initiate
ActiveWorkbook.Sheets(TargetSheetTable).Activate
If ActiveSheet.AutoFilterMode Then
If ActiveSheet.FilterMode Then ActiveSheet.ShowAllData
End If
ActiveSheet.Cells.ClearContents
'Find Range Coordinates Dynamically
ActiveWorkbook.Sheets(SheetTable1).Activate
If ActiveSheet.AutoFilterMode Then
If ActiveSheet.FilterMode Then ActiveSheet.ShowAllData
End If
Range("A1").Select
Selection.End(xlDown).Select
SR1_LastRow = Selection.Row
ActiveCell.SpecialCells(xlLastCell).Select
SR1_LastColumn = Selection.Column
Range("A1").Select
MyLoop = WorksheetFunction.RoundUp(SR1_LastRow / 60000, 0)
NewRowCount = 0
For j = 1 To MyLoop
'Set Up Connection Details
Set MyConn = New ADODB.Connection
MyConn.CommandTimeout = 0
Set MyRecordSet = New ADODB.Recordset
MyConn.Open "Provider = Microsoft.ACE.OLEDB.12.0;" & _
"Data Source = " & Application.ThisWorkbook.FullName & ";" & _
"Extended Properties = ""Excel 12.0 Xml;HDR=YES;IMEX=1"";"
Set MyRecordSet.ActiveConnection = MyConn
'First Time
If SR1_LastRow > 60000 Then
NewRowCount = SR1_LastRow - 60000
SR1_LastRow = 60000
SR1_FirstRow = 1
'Set the tables equal to the respective ranges
Set SheetRange1 = ActiveWorkbook.Sheets(SheetTable1).Range("A" & SR1_FirstRow & ":" & Cells(SR1_LastRow, SR1_LastColumn).Address)
'Pass the table address to a string
Table1 = SheetRange1.Address
'Convert the string into a query table - have to get rid of dollar signs for it to work
Table1 = "[" & SheetTable1 & "$" & Replace(Table1, "$", "") & "]"
'Does this until NewRowCount falls into last time
ElseIf NewRowCount > 60000 Then
NewRowCount = NewRowCount - 60000
SR1_FirstRow = SR1_LastRow + 1
SR1_LastRow = SR1_LastRow + 60000
Set MySheet1 = Sheets(SheetTable1)
Sheets.Add After:=MySheet1
Set MySheet2 = ActiveSheet
MySheet1.Activate
Rows("1:1").Select
Selection.Copy
MySheet2.Activate
Rows("1:1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
MySheet1.Activate
ActiveSheet.Range("A" & SR1_FirstRow & ":" & Cells(SR1_LastRow, SR1_LastColumn).Address).Copy
MySheet2.Activate
ActiveSheet.Range("A2").PasteSpecial xlPasteValues
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Set MyRange = Selection
'Set the tables equal to the respective ranges
Table1 = Selection.Address
'Convert the string into a query table - have to get rid of dollar signs for it to work
Table1 = "[" & MySheet2.Name & "$" & Replace(Table1, "$", "") & "]"
'Last Time
ElseIf (NewRowCount > 0) And (NewRowCount <= 60000) Then
SR1_FirstRow = SR1_LastRow + 1
SR1_LastRow = SR1_LastRow + NewRowCount
NewRowCount = 0
Set MySheet1 = Sheets(SheetTable1)
Sheets.Add After:=MySheet1
Set MySheet2 = ActiveSheet
MySheet1.Activate
Rows("1:1").Select
Selection.Copy
MySheet2.Activate
Rows("1:1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
MySheet1.Activate
ActiveSheet.Range("A" & SR1_FirstRow & ":" & Cells(SR1_LastRow, SR1_LastColumn).Address).Copy
MySheet2.Activate
ActiveSheet.Range("A2").PasteSpecial xlPasteValues
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
'Set the tables equal to the respective ranges
Table1 = Selection.Address
'Convert the string into a query table - have to get rid of dollar signs for it to work
Table1 = "[" & MySheet2.Name & "$" & Replace(Table1, "$", "") & "]"
'Does this the first time if under 60k rows
Else
SR1_FirstRow = 1
'Set the tables equal to the respective ranges
Set SheetRange1 = ActiveWorkbook.Sheets(SheetTable1).Range("A" & SR1_FirstRow & ":" & Cells(SR1_LastRow, SR1_LastColumn).Address)
'Pass the table address to a string
Table1 = SheetRange1.Address
'Convert the string into a query table - have to get rid of dollar signs for it to work
Table1 = "[" & SheetTable1 & "$" & Replace(Table1, "$", "") & "]"
End If
'SQL Statement
MySQL = Sheets("Control Sheet").Range("C14").Value
MySQL = Replace(MySQL, "@Table1", Table1)
MySQL = Replace(MySQL, "@Year", Sheets("Control Sheet").Range("C5").Value)
MySQL = Replace(MySQL, "@FA_PQ_Input", FA_PQ)
MySQL = Replace(MySQL, "@SubChannel", SubChannel)
MySQL = Replace(MySQL, "@MyMonth", MyMonth)
MsgBox MySQL
'Run SQL
MyRecordSet.Open MySQL, MyConn, adOpenKeyset, adLockOptimistic
'Paste Data with headers to location
ActiveWorkbook.Sheets(TargetSheetTable).Activate
ActiveSheet.Range("A" & 1 + SR1_FirstRow).CopyFromRecordset MyRecordSet
For i = 0 To MyRecordSet.Fields.Count - 1
ActiveSheet.Cells(1, i + 1) = MyRecordSet.Fields(i).Name
With ActiveSheet.Cells(1, i + 1)
.Font.Bold = True
.Font.Size = 10
End With
Next i
MyRecordSet.Close
Set MyRecordSet = Nothing
MyConn.Close
Set MyConn = Nothing
Next j
''Putting Nulls in the blanks
'ActiveSheet.Cells.Replace What:="", Replacement:="NULL", LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=True, _
' SearchFormat:=False, ReplaceFormat:=False
'Tidying the sheet
ActiveSheet.Cells.AutoFilter
ActiveSheet.Columns.AutoFit
ActiveSheet.Range("A1").Select
Sheets("Control Sheet").Activate
Application.ScreenUpdating = True
End Sub
Select
иActivate
. Мой совет: избавьтесь от них. Посмотрите здесь, чтобы получить помощь по этому поводу, и тогда вы, вероятно, сами найдете ошибку. Если нет, обновите здесь Q-код безSelect
иActivate
. - person chris neilsen   schedule 20.06.2018