За півтора року мені пропонували купу варіантів того як прискорити читання даних з листа Excel - від використання MSXML і інших готових бібліотек до самопальних процедур і функцій. Що ж, будь-яке завдання можна вирішити кількома способами. Розглянемо кілька варіантів і визначимося який з варіантів виявиться найбільш швидким. Ну, а який варіант виявиться зручнішим - це вже кожен вирішить для себе сам.
Читання даних з Excel
Спочатку розглянемо варіант читання даних використанням якого грішать ті, хто тільки починає своє знайомство з Excel в Delphi - читання даних з кожного осередку окремо. Тестова процедура з таким варіантом читання може виглядати наступним чином:
Лічильник буде в підсумку містити час читання і виведення в StringGrid даних. Можна було б зробити лічильник виключно на читання даних з листа, але я вирішив не перевантажувати исходник зайвими змінними. Якщо буде бажання - можете переписати трохи исходник і отримати "чисте" час читання.
Для тесту цього варіанту був створений лист Excel, що містить 143 рядки і 142 стовпчика з даними, тобто 20306 осередків з даними. На малюнку нижче представлено значення лічильника після читання даних:
12 секунд на читання. а якщо буде 1000 рядків і 1000 стовпців? Так можна і не дочекатися закінчення операції.
Якщо уважно подивитися на процедуру, представлену вище, то можна бачити, що в циклі ми кожен раз при кожній ітерації спочатку отримуємо діапазон, зайнятий даними, потім в цьому діапазоні отримуємо певну комірку і тільки потім зчитуємо значення в осередку. Насправді стільки зайвих операцій для читання даних з листа не потрібно. Тим більше, коли дані розташовуються безперервним масивом. Більш вигідним в цьому випадку варіантом читання буде читання даних відразу з усього діапазону в масив.
На ділі реалізація цього варіанти роботи виявиться навіть простіше, ніж представленого вище. Дивіться самі. Ось варіант читання даних цілим діапазоном:
Дивимося на час виконання операції:
Як бачите, приріст швидкості виявився колосальним, враховуючи навіть те, що в лічильник потрапило час поновлення StringGrid'а.
Тут було б доречно показати і зворотний метод роботи з Excel, тобто запис даних на лист Excel з використанням варіантного масиву.
Запис даних в Excel
У разі, якщо нам необхідно записати великий обсяг даних на лист Excel нам необхідно провести зворотну операцію, тобто спочатку створити варіантний масив, потім записати в цей масив дані після чого записати весь масив однією операцією в Excel. Для прикладу я написав процедуру, яка зчитує великий обсяг даних з StringGrid і записує ці дані на другий лист відкритої книги Excel:
Тут ми спочатку створюємо двовимірний варіантний масив, використовуючи метод VarArrayCreate, після чого заповнюємо масив даних і передаємо цей масив в Excel. Зверніть увагу, що під час запису в Excel не використовуються ніякі цикли - запис відбувається в 2 простих дії:
- виділяємо діапазон, використовуючи в якості меж діапазону першу і останню осередки
- присвоюємо діапазону значення з масиву.
Для повноти картини нижче на малюнку представлено значення лічильника, який відрахував час від моменту створення масиву до активації програми Excel включно:
Природно, що з ростом обсягу даних буде рости і час виконання операції. Так, наприклад, лист, який містить 1000 рядків і 256 стовпців з даними заповнювався близько 7 секунд. Якщо для Вас такий час неприйнятно, то представлена вище процедура може бути трохи прискорена використанням пари методів VarArrayLock () і VarArrayUnLock (), але при цьому слід враховувати, що матриця FData буде транспонована.
Що ще варто сказати з приводу читання / запису даних в Excel? Напевно те, що запропоновані вище методи роботи в обов'язковому порядку вимагають наявності встановленого Excel на тому комп'ютері де запускається Ваша програма. У зв'язку з цією обставиною може знадобитися більш універсальний спосіб роботи з Excel. Тут, знову ж таки, може бути кілька варіантів роботи, але я покажу, а точніше вкажу лише на один з них - з використанням бібліотека XLSReadWrite.
Спрощений приклад для Delphi 7
Повний приклад роботи з бібліотекою: