Реалізація експорту даних (CSV, Excel) з мобільного додатку
Користувач натискає «Експортувати» — і чекає. Якщо у нього 5000 рядків у локальній SQLite або Room-базі, а експорт відбувається на main thread, додаток завмирає на секунди три, а на старих пристроях ANR (Application Not Responding) не змусить себе чекати. Це перша і найчастіша помилка при реалізації експорту. Ми у своїй практиці стикаємося з такими ситуаціями постійно і виробили надійний підхід, який гарантує стабільну роботу навіть на пристроях з 2 ГБ ОЗУ.
Наші інженери з семирічним досвідом у мобільній розробці виконали понад 50 проектів з експортом даних. Кожен проект проходив через тестування на реальних даних з обсягом до 500 000 рядків. Зв'яжіться з нами — розберемо вашу архітектуру за 30 хвилин.
Чому кодування — це пастка
CSV — це пастка. Excel у Windows за замовчуванням очікує кодування Windows-1252 та роздільник `;`, а не `,`. Якщо віддати UTF-8 без BOM — кирилиця перетворюється на кракозябри. Правильний CSV для Excel: UTF-8 з BOM (`\uFEFF` на початку файлу) та роздільник `;`. Або одразу експортувати `.xlsx` через бібліотеку.Що на практиці ламається найчастіше
Блокування UI при генерації файлу. Серіалізація 10 000 рядків у CSV — це не «миттєва операція». На Android потрібен CoroutineScope(Dispatchers.IO), на iOS — DispatchQueue.global(qos: .userInitiated). Генерацію файлу завжди виносимо у фоновий потік, результат повертаємо через callback або Flow.
Кодування та роздільник. CSV — це пастка. Excel у Windows за замовчуванням очікує кодування Windows-1252 та роздільник ;, а не ,. Якщо віддати UTF-8 без BOM — кирилиця перетвориться на кракозябри прямо в офісі клієнта. Правильний CSV для Excel: UTF-8 з BOM (\uFEFF) та роздільник ;. Або одразу експортувати .xlsx через бібліотеку.
Експорт в Excel (.xlsx). На Android використовуємо Apache POI або легший FastExcel. На iOS — xlsxwriter через Swift Package або власний XML-генератор (.xlsx — це ZIP з XML-файлами всередині). Для React Native є react-native-xlsx поверх js-бібліотеки xlsx.
Як ми будуємо експорт
Схема проста: читаємо дані з локальної БД → трансформуємо в модель рядка → пишемо у файл → ділимося через системний ShareSheet / Intent.ACTION_SEND.
На Android з Room це виглядає так:
viewModelScope.launch(Dispatchers.IO) { val rows = database.transactionDao().getAll() val file = CsvExporter.export(rows, context.cacheDir) withContext(Dispatchers.Main) { shareFile(file, "text/csv") } } На iOS аналогічно через Task.detached:
Task.detached(priority: .userInitiated) { let rows = await store.fetchAll() let url = try CsvExporter.write(rows, to: .cachesDirectory) await MainActor.run { presentShareSheet(url) } } Для .xlsx на iOS генеруємо XML-структуру вручну або через CoreXLSX / xlsxwriter. Для простих таблиць — XML-підхід швидше і без залежностей.
Прогрес при великому обсязі
Якщо рядків більше 50 000 — показуємо ProgressView з реальним відсотком. На Android через StateFlow<Int> у ViewModel, на iOS через @Published var progress: Double. Пишемо файл батчами по 1000 рядків, оновлюємо лічильник після кожного батча.
Формат файлу та Share
Після генерації файл кладемо в cacheDir (Android) або FileManager.default.temporaryDirectory (iOS). Ділимося через:
- Android:
FileProvider+Intent.ACTION_SENDз правильним MIME-типом (text/csvабоapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet) - iOS:
UIActivityViewControllerз[fileURL]
Не зберігаємо в Downloads без явного запиту користувача — це порушує гайдлайни обох платформ.
Чому експорт на фоновому потоці критичний?
Будь-яка робота з I/O та серіалізацією повинна бути винесена з головного потоку. На практиці це скорочує час відгуку додатку в 5–10 разів для вивантажень від 10 000 рядків. Наші інженери перевіряють це на кожному проекті.
Як коректно відображати кирилицю в CSV для Excel?
Використовуйте UTF-8 з BOM та крапку з комою як роздільник. Альтернатива — експорт у .xlsx, де кодування не викликає проблем. У нас є досвід адаптації експорту для локальних ринків, включаючи кирилицю та азійські символи.
Покрокова інструкція з реалізації експорту
- Вибір формату (CSV або XLSX) та узгодження структури колонок.
- Читання даних з БД у фоновому потоці.
- Генерація файлу з коректним кодуванням та роздільниками.
- Відображення прогресу при великих обсягах.
- Шаринг через системний діалог.
Що входить у роботу
- Вибір формату (CSV / XLSX) та узгодження структури колонок.
- Фонова генерація файлу без блокування UI.
- Коректне кодування та локалізація роздільників.
- Індикатор прогресу для великих вивантажень.
- Шаринг через системний ShareSheet / Intent.
- Тести на реальних обсягах даних.
Терміни
Простий CSV-експорт з готової бази даних: 0,5–1 день. З вибором формату (CSV/XLSX), фільтрами за діапазоном дат та прогресом: 1,5–2 дні. Вартість розраховується після аналізу структури даних — оцінимо проект безкоштовно. Зв'яжіться з нами, щоб обговорити вашу задачу. Отримайте консультацію по вашому проекту — ми допоможемо обрати формат та оцінимо обсяг робіт.
| Формат | Складність реалізації | Підтримка форматування | Залежності |
|---|---|---|---|
| CSV | Низька | Немає | Мінімум |
| XLSX | Середня | Так | Бібліотеки Apache POI / xlsxwriter |
| Обсяг даних | Рекомендований формат | Приблизний час генерації |
|---|---|---|
| < 10 000 | CSV або XLSX | < 1 секунди |
| 10 000 – 100 000 | XLSX | 1–10 секунд |
| > 100 000 | CSV (батчами) | 10+ секунд, потрібен прогрес |







