Что нового

_Excel_RangeRead отправляет в массив пустые ячейки

Shinoby

Новичок
Сообщения
81
Репутация
2
:stars: При использовании этой функции отправляет в массив максимум ячеек.
все что смог выяснить, так это то, что если файл xls (любой версии) то массив получается длинной 65536, а если xlsx то 1048576 :stars: :stars: при том, что на самом деле сколько в столбце не пустых ячеек не имеет значение. (пробовал файлы и парой десятков ячеек и 10000 ячеек - результат одинаков).
ячейки пустые, т.е. никаких формул в них нет и не было.

единственное что нашел на форуме, это идею удалять пустыне ячейки... но при каждом запуске скрипта удалять более миллиона ячеек это перебор.

win7-64, exel 2010, autoit 3.3.7 (обновил до 3.3.14 - результат такойже, только теперь еще и русский текст в скрипте заменяет на вопросы)

может опция где есть?
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Вы указали какие именно ячейки надо отправить в массив?

Код:
#include <Excel.au3>
Local $oExcel = _Excel_Open()
Local $oWorkbook = _Excel_BookOpen($oExcel, @ScriptDir & "\tst.xlsx")
Local $sResult = _Excel_RangeRead($oWorkbook, Default, "A1:A15") ;берем 1й столбец с 1 по 15 строки
For $i in $sResult
	ConsoleWrite($i & @CRLF)
Next
 
Автор
S

Shinoby

Новичок
Сообщения
81
Репутация
2
Количество используемых строк заранее не определено.
по этому использую такой формат:
Код:
Local $aArray = _Excel_RangeRead($oWorkbook, 1, "A:B")


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

но она более не доступна :(

можно сократить объем строк до количества больше которого не должно быть при любых раскладах, типа 20000. но это тоже черт знает что...
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Предварительно вычислить последнюю не пустую ячейку в столбце:

Код:
#include <Excel.au3>
Global Const $xlUp = -4162
Local $oExcel = _Excel_Open()
Local $oWorkbook = _Excel_BookOpen($oExcel, @ScriptDir & "\tst.xlsx")

With $oWorkbook.ActiveSheet
    $countRow = .Cells(.Rows.Count, "A").End($xlUp).row
EndWith

Local $sResult = _Excel_RangeRead($oWorkbook, Default, "A1:A" & $countRow)

For $i in $sResult
    ConsoleWrite($i & @CRLF)
Next
 
Автор
S

Shinoby

Новичок
Сообщения
81
Репутация
2
вот по тому же пути мысли пошли, только нашел видимо более толстый вариант:
Код:
Local Const $xlUp = -4162
With $oWorkbook.ActiveSheet ; process active sheet
	$oRangeLast = .UsedRange.SpecialCells($xlCellTypeLastCell) ; get a Range that contains the last used cells
	$iRowCount = .Range(.Cells(1, 1), .Cells($oRangeLast.Row, $oRangeLast.Column)).Rows.Count ; get the the row count for the range starting in row/column 1 and ending at the last used row/column
	$iLastCell = .Cells($iRowCount + 1, "B").End($xlUp).Row ; start in the row following the last used row and move up to the first used cell in column "B" and grab this row number
	ConsoleWrite("Last used cell in column B: " & $iLastCell & @CRLF)
EndWith

(это просто для справки, вдруг кому пригодится)


но проблемы это не решило.
что такой вариант, что
Код:
Local $aArray = _Excel_RangeRead($oWorkbook, 2 )

что
Код:
Local $aArray = _Excel_RangeRead($oWorkbook, 2, Default )

что
Код:
Local $aArray = _Excel_RangeRead($oWorkbook, 2, "A1:B9241" )
(в данный момент там 9241 строка)

выдает ошибку: 5 и расширенную: -2147352571




Добавлено:
Сообщение автоматически объединено:

причем это происходит при количестве строк больше 4000 (я прыгал по 1000 и на 4241 уже была эта же ошибка) :stars: :stars:
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Хм... странно у меня работает (при условии, что 2й лист существует в книге):

Код:
#include <Excel.au3>
#include <Array.au3>
Global Const $xlUp = -4162
Local $oExcel = _Excel_Open()
Local $oWorkbook = _Excel_BookOpen($oExcel, @ScriptDir & "\tst.xlsx")
With $oWorkbook.ActiveSheet
    $countRow = .Cells(.Rows.Count, "A").End($xlUp).row
EndWith

Local $sResult = _Excel_RangeRead($oWorkbook, 2, "A1:B" & $countRow)

_ArrayDisplay($sResult)
 
Автор
S

Shinoby

Новичок
Сообщения
81
Репутация
2
нашел беду :mad:
при встречи с первой ячейкой в которой 256 символов или больше вываливается эта ошибка.

Причем в Excel.au3 упоминается об ограничение на количество ячеек в зависимости от версии экселя, но нет ничего про размер ячейки.


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


Добавлено:
Сообщение автоматически объединено:

:shok: :shok: :shok: да... но ведь когда я использовал комбинацию
Код:
Local $aArray = _Excel_RangeRead($oWorkbook, 2, "A:B" )
- все прекрасно считывалось без ошибок...


Добавлено:
Сообщение автоматически объединено:

но с обилием пустых ячеек


Добавлено:
Сообщение автоматически объединено:

а вот и еще дополнение в моих изысканиях:

Код:
Local $aArray = _Excel_RangeRead($oWorkbook, 2, "A3520" )


в этой ячейке строка длинной более 255 символов.

функция возвращает пустую строку, при этом выполнение завершается без ошибки. вот такой облом.
т.е. вариант решения задачи только такой: считывать все столбцы в формате А:В, а затем зная количество не пустых строк/столбцев делать новый массив через
Код:
_ArrayExtract
уже без пустых строк.

есть еще идеи?
 
Автор
S

Shinoby

Новичок
Сообщения
81
Репутация
2
c vba - не знаком.

интуитивно понимаю что означают некоторые конструкции, но сам создавать их не умею.
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Потестил в 256+ символов, ячейка не пустая.

Код:
#include <Excel.au3>
#include <Array.au3>

Global Const $xlUp = -4162
Local $oExcel = _Excel_Open()
Local $oWorkbook = _Excel_BookOpen($oExcel, @ScriptDir & "\tst.xlsx")
With $oWorkbook.ActiveSheet
    .Worksheets(2).Select
	$countRow = .Cells(.Rows.Count, "A").End($xlUp).row ;подсчитываем vba кол-во строк
	$arr = .Range(.Cells(1, 1), .Cells($countRow, 2)).Value2 ;формируем массив в vba
EndWith

_ArrayDisplay($arr)
 
Автор
S

Shinoby

Новичок
Сообщения
81
Репутация
2
:smile: эту конструкцию попробую осознать.

вопрос финальный: а как через vba считать конкретную ячейку?

правильно ли догадываюсь?
Код:
$CelText = .Cells(5, 3)


где значение будет взято из 5го столбца и 3й строки
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Код:
$CelText = .Cells(5, 3) ;сама ячейка пятой строки, третий столбец

$CelText = .Cells(5, 3).Value ;значение, содержащееся в ячейке

With $oWorkbook.ActiveSheet ;берем открытый Excel и работаем с активным листом
    .Worksheets(2).Select ;переключаемся на лист 2, если данные на 2м листе
    $countRow = .Cells(.Rows.Count, "A").End($xlUp).row ;подсчитываем кол-во не пустых строк в столбце А
    $arr = .Range(.Cells(1, 1), .Cells($countRow, 2)).Value2 ;берем все ячейки от А1 (Cells(1,1)) до Bx, где x = номер последней непустой строки в столбце А
; с массивом можем работать напрямую из AutoIt
EndWith
 
Верх