Перейти до основного вмісту

Qt + Microsoft Excel 2003 XML

Останнім часом все більше часу приділяю розробці програм для машинної обробки прайс-листів. Прайси приходять в різних форматах xml, xls, txt, csv. І найчастіше результат готую в csv для завантаження його в інтернет магазин. Але не так давно з'явився клієнт, який побажав результат в xslx. У нього самопісний сайт і він хотів би деяке візуальне оформлення, наприклад, підсвітити кольором певні або проблемні позиції, в заданій умові.

Але я працюю з Ubuntu і скажемо так, xlsx - тут не зовсім зручний формат. Честно зізнаюся, я зневірився адже засобами CSV такого не реалізувати. Фактично я вирішив перемогти цю проблему найпростішим шляхом і вже почав готувати "запасний" Windows, щоб там налагодити тандем Qt + Excel. І в цьому процесі я натрапив на формат Microsoft Excel 2003 XML. Пошук в Google дав небагато інформації, частково навіть не помилкової, але всеж таки перспективною.

Перше, що я зробив - це створив файл в Calc. Невеличку таблицю 4х3, виділив деякі клітини кольором, десь поставив жирний шрифт. Зберіг файл у форматі Microsoft XML 2003 XML. На виході виявився звичайний XML файл.

Відкрив я його в Sublime Text - ну, що звичайний xml. Нічого цікавого, структура логічна і абсолютно зрозуміла. Я вирішив, що таким чином цілком зможу передати потрібну інформацію після обрабки прайс-листа. Потім відкрию його в Calc, перевірю правильність підсвічування, перезберегу в xlsx і обойдустя без Windows. Так я і зробив. Один в один передав структуру, як в збереженому прикладі, вивантажив для проби 10 рядків.

Цікаво, що файл в цей формат зберігається швидше, незважаючи на те, що даних в кілька разів більше.

В результаті Calc не відкрив мій файл. Фактично він навіть не говорить, де у мене помилка.

Пересів за Windows. Excel 2007 його теж не відкрив, але в процесі відкриття лаявся досить конкретно. Після 10-12 спроб і наступних виправлень я здався. Незважаючи на першу поразку, я все-таки вирішив спробувати зайти з іншого боку. Тестовий файл я зберіг тепер в Excel, все-таки це його рідний формат, а не Calc. Відкривши його в Notepad++ знайшлося досить багато відмінностей, імовірно через які мій файл і не відкривався. Після коригування коді програми відповідно до другого тестового файлу прийшов успіх. Все відкривалося і в Calc, і Excel, з потрібною передачею стилів і підсвічуванням необхідних даних.

Але не обійшлося без нюансів. Я потім збирав і довші файли (>70000 рядків), так ось їх Calc не відчиняє. Довго міркує, явно страждає при цьому і не відкриває. Excel 2007 все відкриває швидко і без проблем, так що зовсім без Windows не вдалося.

В деталях, як і що я робив, а краще як потрібно робити щоб вийшло з першого разу розповім і картинки покажу в наступних постах.

Коментарі

Популярні дописи з цього блогу

QString в HEX и обратно

Спочатку з QString робимо QByteArray. Зауважимо, якщо у вас по тексту тільки латинські букви цілком підійде варіант з .toUtf8(). Якщо ж присутня і кирилиця - обов'язково використовуємо .toLocal8Bit(). QString strA = "Some text"; QByteArray bA = strA.toLocal8Bit().toHex(); Перетворення QByteArray в початковий текст має такий вигляд: QString strB = QString::fromLocal8Bit(QByteArray::fromHex(bA))); Цікаво, що якщо ми для зберігання записали отриманий Нех куди-небудь, наприклад, в файл або базу даних у вигляді текстового рядка, то для зворотного перетворення цей рядок потрібно додатково перетворити в QByteArray. QString strA2 = QString::fromUtf8(bA); QByteArray bB = strA2.toUtf8(); QString strB = QString::fromLocal8Bit(QByteArray::fromHex(bB)));

Qt та Excel. Робота з ячейками.

Для доступу до всіх властивостей і вмісту ячійок у Excel використовуються два об'єкти Range і Cells. Між ними є тільки одна відмінність (крім назви) - перший об'єкт забезпечує доступ до області ячійок та його аргументом є строка. QAxObject *myRange; myRange = sheetAct->querySubObject("Range (QVariant)", "A1:D3"); myRange->dynamicCall("Select()"); / / виділяємо діапазон ячійок Cells забезпечує доступ тільки до однієї ячійки і аргументом є номер рядка і стовпця. Таким чином запис виду: QAxObject *myRange; myRange = sheetAct->querySubObject("Range(QVariant)", "A2"); і QAxObject *myCells; myCells = sheetAct->querySubObject("Cells (Int, Int)", 1, 2); є рівнозначною. Щоб визначити реальну адресу ячійки або діапазону ячійок можна скористатися властивістю Address, яке має наступні параметри: RowAbsolute, ColumnAbsolute, ReferenceStyle, External, RelativeTo. myRange = sheetAct->querySubObject(...

Qt Округлення до певного розряду

Округлення - тривіальна задача в математиці, але в Qt немає функції округлення до певного розряду. Проте в QtMath є такі функції як qFloor (qreal) і QCeil (qreal), в результаті яких int. А також можна використовуючи round (double), отримати double. Дуже швидко я знайшов ось цей ресурс звідки взяв вихідну формулу. Вона без сумніву працює, але дає результати, які не відповідаю моїм очікуванням: toRound(187.156, 2); //187.15 toRound(187.156, 1); //187.1 toRound(187.156, 0); //187 toRound(187.156, -1); //180 toRound(187.156, -2); //100 Після невеликої корекції самої функції, її підсумковий варіант виглядає так: double wcsv::toRound(double val, int r) {   double outpValue;   double tempVal;   tempVal=val*pow(10,r);   if (double(int(tempVal))+0.5==tempVal){     int(tempVal)%2 == 0       ? outpValue=double(qFloor(tempVal))/pow(10,r)       :outpValue=d...