Участник
Регистрация: 28.11.2005
Адрес: Москва
|
Цитата:
Сообщение от Gustav
По классу - пара пожеланий. Первое. Я бы объединил методы getFieldValue и getNamedFieldValue в один универсальный getFieldValue. И плюс к этому нумерацию полей начал бы с единицы, невзирая на то, что в самом ADO первое поле - 0. Понимаю, что вопрос концептуально-идеологический. Я сам метался между 0 и 1, но в конце концов остановился на 1. Ну и что, что лишняя операция вычитания, зато получается нормальный наглядный натуральный ряд (блин, ненавижу циклы от 0 до Count-1).
Fixed Я тоже сначала думал, как делать индексацию полей и по номерам, и по названиям колонок, но чего-то совсем забыл про anytype Кроме того, нумерация начиная с 1 применительно к Excel, конечно, куда удобнее - в нем ведь тоже можно включить нумерацию колонок ("стиль ссылок R1C1"), а там она начинается как раз с 1.
Цитата:
У меня в "инструментальном ящичке" в некотором классе есть противоположный метод - setFieldValue, привожу его в качестве подспорья-иллюстрации. Воспользуйтесь при желании.
PHP код:
void setFieldValue(anytype _fldName, anytype _fldValue, int _ordNum = 0)
{
// _fldName - можно текстовое имя, а можно числовое, начиная с 1 (!), а не 0 как в самом ADO
// _ordNum - дополнительный способ нумерации, если используются текстовые названия полей (чисто для наглядности самого кода)
anytype fldName;
if (typeof(_fldName) == Types::Integer)
fldName = _fldName - 1;
else
fldName = _fldName; // текстовое представление поля
fld = flds.Item(fldName);
fld.Value(_fldValue);
}
Честно говоря, не понял две вещи: зачем нужен параметр _ordNum, если он не используется, и зачем идет дополнительное присваивание fldName = _fldName. У меня работает просто такой код:
PHP код:
if(typeof(_fldId) == Types::Integer)
_fldId--; // ADO uses indexes starting 0, not 1
fld = flds.Item(_fldId);
А так, иллюстрацией я уже воспользовался
Цитата:
Второе пожелание. В методе getRecordCount я бы не торопился возвращать -1 в случае невозможности определения кол-ва записей через ADO. Всё же класс посвящен Excel'ю, а он нам не чужой. Можно, например, воспользоваться в Excel методом Range.CurrentRegion и далее Rows.Count минус первая заголовочная строка (если она есть). Ну, как-то так...
Меня, по правде сказать, вопрос использования Excel'евских COM-интерфейсов несколько смущает... Все же упор сделан на ADO, и экселевской специфики в классе - только определение названия активного листа, которое используется как название таблицы в выборке, да еще формат строки соединения... Во-первых, меня смущают такие вещи, как производительность: надо, конечно, тесты провести, но, сдается мне, если грузить Excel для того, чтобы посчитать количество строк в диапазоне, то это вызовет заметную задержку при открытии файла. Во-вторых, количество строк в диапазоне (range) и количество строк в выборке совпадут лишь в том случае, если использовать для получения Recordset обычный select * from. Но если развивать идею дальше, то select может оказаться с where, да еще и по нескольким листам книги Excel, и тогда в Recordset.RecordCount будет вовсе не равно Range.CurrenRegion.Rows.Count-1. В-третьих, в ADO и так есть возможность получить число строк в выборке, например, использовать статический курсор, а не forward-only, который используется в классе по умолчанию. Достаточно при создании экземпляра класса написать
PHP код:
#CCADO
// ...
excelImp = new Uni_ExcelImportADO(strFileName, #adOpenStatic);
Правда, опять-таки, это приводит к задержкам при открытии файла, потому что приходится для подсчета считывать все данные в буфер перед тем, как начать выдавать их. Впрочем, я сейчас провел небольшой тест, и выяснилось, что в простейших случаях это не столь критично. Для файла из 4-х полей (цифровой код, текстовое описание от 30 до 120 символов, еще два цифровых поля) и 8000 записей при 5 последовательных тестах на каждый этап среднее время у меня составило:- открытие 456 мс, считывание данных 8093 мс, курсор forward-only, имя листа определяется классом;
- открытие 456 мс, считывание данных 8172 мс, курсор статический, имя листа определяется классом;
- открытие 22 мс, считывание данных 7960 мс, курсор forward-only, имя листа указано в параметре;
- открытие 22 мс, считывание данных 8067 мс, курсор статический, имя листа указано в параметре.
Измерения велись с помощью GetTickCount(), открытие - это создание экземпляра класса + вызов openFile(), считывание данных - это цикл выборки трех полей из каждой записи.
В общем, мне кажется, идеологически правильнее использовать для определения количества записей средства ADO, а не обходные маневры с использованием COM-интерфейсов Excel.
Во вложении - тестовый job, использованный для измерения скорости. Обновленный класс можно найти в первом сообщении темы.
Последний раз редактировалось gl00mie; 08.01.2007 в 23:45.
|