LaGir, Спасибо за статью!
Может сталкивался кто-нибудь с похожей задачей?
Коротко: "Нужно сделать добавление данные в таблицы с ожиданием окончания записи"
Есть файл "Тест.xlsx"
Записываю в него данные. (больше 5 разных ячеек)
Следующим действием идёт отправка файла POST запросом.
Часто, так как отправка файла идёт сразу после действий по "записи данных", то файл отправляется без фактически записанных данных и после этого данные записываются на локальном файле. (а POST запросом отправился недописанный файл).
LaGir, Спасибо за статью!
Может сталкивался кто-нибудь с похожей задачей?
Коротко: "Нужно сделать добавление данные в таблицы с ожиданием окончания записи"
Есть файл "Тест.xlsx"
Записываю в него данные. (больше 5 разных ячеек)
Следующим действием идёт отправка файла POST запросом.
Часто, так как отправка файла идёт сразу после действий по "записи данных", то файл отправляется без фактически записанных данных и после этого данные записываются на локальном файле. (а POST запросом отправился недописанный файл).
Спасибо, Phoenix78
Сделал дополнительную таблицу, которую "привязывал к файлу" и проверял фактическую запись данных в локальный файл.
По тестам, хватало до 30 - 40 секунд для записи.
Компиляция кода Ошибка в действии "CS0246" "The type or namespace name 'ExcelPackage' could not be found (are you missing a using directive or an assembly reference?)". [Строка: 34; Cтолбец: 8]
Компиляция кода Ошибка в действии "CS0246" "The type or namespace name 'ExcelPackage' could not be found (are you missing a using directive or an assembly reference?)". [Строка: 34; Cтолбец: 34]
Компиляция кода Ошибка в действии "CS0246" "The type or namespace name 'ExcelWorksheet' could not be found (are you missing a using directive or an assembly reference?)". [Строка: 37; Cтолбец: 2]
либа с гитхаба(тоже самое и с другими с других мест в том числе тут в теме на 1 странице кто то прикреплял dll готовый), не пойму че надо
Зенно Постерович v 7.4.0.0
либа с гитхаба(тоже самое и с другими с других мест в том числе тут в теме на 1 странице кто то прикреплял dll готовый), не пойму че надо
Зенно Постерович v 7.4.0.0
У меня основная задача - писать данные в нужном формате. Всякие красивости не нужны.
Я в цикле готовлю данные и потом пишу в таблицу сразу всю строку, например
{-Variable.date-}{-String.Tab-}{-Variable.var1-}{-String.Tab-}{-Variable.var2-}
в строке разные данные - и дата и простые числа и double
Подскажите как адаптировать код, чтобы записывать данные в нужном формате. Формат парсить не нужно, я могу указать в явном виде, структура таблицы не меняется.
Я в цикле готовлю данные и потом пишу в таблицу сразу всю строку, например
{-Variable.date-}{-String.Tab-}{-Variable.var1-}{-String.Tab-}{-Variable.var2-}
в строке разные данные - и дата и простые числа и double
если ты работаешь с одним листом, так может тебе просто использовать CSV файл, тогда через разделитель формируешь строку и записываешь, как в обычный текстовый файл.
А при просмотре CSV файл можно открывать как таблицу указав разделитель при открытии файла.
если ты работаешь с одним листом, так может тебе просто использовать CSV файл, тогда через разделитель формируешь строку и записываешь, как в обычный текстовый файл.
А при просмотре CSV файл можно открывать как таблицу указав разделитель при открытии файла.
Да у меня в этом же файле сводная хранится, данные постоянно прибавляются, в сводной анализирую. Если писать в CSV, то нужно будет пересохранять в xls, лишние действия.
У меня основная задача - писать данные в нужном формате. Всякие красивости не нужны.
Я в цикле готовлю данные и потом пишу в таблицу сразу всю строку, например
{-Variable.date-}{-String.Tab-}{-Variable.var1-}{-String.Tab-}{-Variable.var2-}
в строке разные данные - и дата и простые числа и double
Подскажите как адаптировать код, чтобы записывать данные в нужном формате. Формат парсить не нужно, я могу указать в явном виде, структура таблицы не меняется.
Спасибо. Пользуюсь вот этим, но тяжелые запросы не всегда обновляет. Может времени не хватает, конечно. Думал в этой библиотеке есть что-то похожее
var path = project.Variables["path"].Value;
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.DisplayAlerts = false;
Workbook theWorkbook = excelApp.Workbooks._Open(path, 0, false, 5, System.Reflection.Missing.Value, System.Reflection.Missing.Value, false, System.Reflection.Missing.Value, System.Reflection.Missing.Value, true, false, System.Reflection.Missing.Value, false);
theWorkbook.RefreshAll();
Второй кубик из примера не запускается, выдает ошибку: "
Выполнение действия CSharp OwnCode: Генерация Excel. [Строка: 162; Cтолбец: 0] Не удалось загрузить файл или сборку "EPPlus, Version=4.1.0.0, Culture=neutral, PublicKeyToken=ea159fdaa78159a1" либо одну из их зависимостей. Найденное определение манифеста сборки не соответствует ссылке на сборку. (Исключение из HRESULT: 0x80131040)"
Второй кубик из примера не запускается, выдает ошибку: "
Выполнение действия CSharp OwnCode: Генерация Excel. [Строка: 162; Cтолбец: 0] Не удалось загрузить файл или сборку "EPPlus, Version=4.1.0.0, Culture=neutral, PublicKeyToken=ea159fdaa78159a1" либо одну из их зависимостей. Найденное определение манифеста сборки не соответствует ссылке на сборку. (Исключение из HRESULT: 0x80131040)"
Здравствуйте, подскажите пожалуйста, есть ли способ как то ускорить заполнение? В данном варианте отчет, примерно 60 тыс строк. Из приведенного сниппета убран второй лист и убрано распознавание дат, оставлено только распознавание целого и дробного числа. Отчет забирается по апишке, сам зеннопостер парсит его в таблицу примерно за 5 минут. И больше 4х часов происходит заполнение именно сниппетом. Причем эту же самую таблицу в 10 тыс строк, сниппет заполняет примерно за 10 минут.
Наверняка многие из вас создавали шаблоны-парсеры. И, как правило, результаты в этом случае на выходе помещали в Excel-таблицы. Функционала ZennoPoster хватает для осуществления этих задач, за исключением несколько нюансов. Например, отсутствуют возможности для стилизации выходных таблиц, работать можно исключительно с первым листом, записывать данные можно только в строковом формате. Нет прочих различных плюшек, доступных в Excel.
Согласитесь, куда приятнее, когда на выходе получаешь вторую табличку, а не первую (см. скриншоты ниже). А если делаем парсер на заказ, а не для своих личных целей – и говорить нечего. Именно об этом и пойдёт речь в статье – как максимально просто получить красивый Excel-отчёт в ZennoPoster, с нуля до конкретного результата.
Недавно, с версии 5.10.0.0, со стороны ZennoPoster лёд чуть-чуть тронулся – появились методы для редактирования стилей ячеек через C#-сниппеты. Однако, пока сложно сказать, что это хотя бы отчасти решило проблему. Возможности самые базовые, опять же только стили, и в любом случае их надо задавать через код – для тех, кто использует чисто кубики, по сути ничего не изменилось.
Поэтому, данный способ нам не совсем подходит. Что же делать?
Думаю, многим из вас известен альтернативный метод – использование сторонней dll-библиотеки, с помощью которой можно воплотить большую часть возможностей Excel. Однако, есть одна существенная проблема – всё оформление таблиц опять же надо писать через C#-код, и даже для той сравнительно простой желанной таблички с картинки выше – его нужно написать достаточно много. Ну и конечно, для этого надо уметь в нём неплохо разбираться. На форуме, кстати, есть статья об использовании такой библиотеки, но, к сожалению, там опять же описаны только самые азы применения стилей и форматирования – те же, которые появились в ZP v5.10.
Тем не менее, мы остановимся именно на этом способе – так как у библиотеки, которую мы будем использовать (а именно известный и могучий EPPlus), есть одна шикарная фича – создание таблиц по шаблону.
Что это значит? То, что мы можем создать xlsx-файл, нарисовать в нём вручную в Excel всё оформление – а в ZennoPoster использовать его как шаблон стилей для результирующего файла. Всё, что нам останется – вставить в область данных результаты парсинга.
Без кода тут, конечно, всё равно не обойтись, но его совсем немного. Главное и самое сложное - оформление - мы делаем руками в Excel, соответственно - нам не потребуются программерские способности и не придётся убить кучу времени на копание в документации библиотеки.
Вводную часть закончили, приступим к делу.
Подготовка шаблона оформления
Собственно, рисуем в Excel заголовки и их стили, выравниваем всё, добавляем другие вещи по желанию (например, строку фильтра).
Так как стандартными средствами ZennoPoster можно работать только с первым листом Excel-файла (тоже порой весьма неприятное ограничение), рассмотрим пример с заполнением 2 листов.
Для примера нарисовал такие таблички. Также сразу добавил фильтры, закрепил области заголовков, кое-где добавил примечания. Над тематикой содержимого особо не заморачивался и взял первое что пришло в голову, соответственно, по этому поводу просьба не пинаться – всё это чисто для примера. Посмотреть вложение 17269Посмотреть вложение 17270
Сохраняем файл в папке с проектом, я назвал его Template.xlsx.
Подключение библиотеки
Теперь нам нужно подключить к нашему проекту саму библиотеку EPPlus.
Наверняка многие умеют подключать dll-библиотеки, но на всякий случай разберём под спойлером по шагам.
2. Определяем значения стартовых рядов и столбцов. Например, если первый ряд листа занимают заголовки столбцов, а со второго начинаются сами данные – значением стартового ряда будет 2. Со столбцами аналогично.
C#:
//Определяем ряд итоговой таблицы, с которого будем вставлять данныеint startRowT1 =3;//Для первого листаint startRowT2 =4;//Для второго листа//Определяем столбец итоговой таблицы, с которого будем вставлять данныеint startColT1 =1;//Для первого листаint startColT2 =1;//Для второго листа
Если нужно получить начальный ряд или столбец из переменной проекта, определяем переменные следующим образом:
C#:
int startRowT1 =int.Parse(project.Variables["Peremennaya"].Value);
3. Объявляем вспомогательные переменные для типов данных в ячейках итоговой таблицы – они понадобятся нам чуть позже.
C#:
DateTime dt;double d;int i;
4. Получаем наш файл-шаблон Template.xlsx из директории проекта. Сразу делаем проверку на его наличие.
C#:
FileInfo template =newFileInfo(project.Directory +@"\Template.xlsx");if(!template.Exists){//Делаем проверку - если Template.xlsx отсутствует - выходим по красной ветке
project.SendErrorToLog("Упс! Файл Excel-шаблона 'Template.xlsx' отсутствует в директории проекта.",true);returnnull;}
5. Создаём объект нашего Excel-документа на базе Template.xlsx. Отныне весь дальнейший код будем писать внутри данных фигурных скобок.
C#:
using(ExcelPackage exPack =newExcelPackage(template,true)){//Тут будет весь дальнейший код. А именно://Работа с 1 листом//Работа со 2 листом//Сохранение файла}
6. Прежде чем начать работу с листами, их нужно определить/получить из шаблона. Сделаем это по их порядковым номерам.
7. Далее, нам нужно записать в первый лист данные из первой таблицы проекта. Это можно сделать в двойном цикле, вот так:
C#:
for(int row = startRowT1; row < table1.RowCount+startRowT1; row++){for(int col = startColT1; col < table1.ColCount+startColT1; col++){
ws1.Cells[row,col].Value = table1.GetCell(col-startColT1, row-startRowT1);}}
…но мы этого делать не будем, так как в этом случае все данные запишутся в обычном строковом формате (все данные стандартных таблиц Zenno хранятся как строки). Библиотека позволяет нам записывать в Excel-файл данные именно тех типов, которые нам нужны, и мы этим воспользуемся.
C#:
for(int row = startRowT1; row < table1.RowCount+startRowT1; row++){for(int col = startColT1; col < table1.ColCount+startColT1; col++){//Пробуем распознать тип вставляемых данных - дату, целое число, дробное числоif(DateTime.TryParse(table1.GetCell(col-startColT1, row-startRowT1),out dt)){//Если распознали, например, дату (тип DateTime) - сразу меняем формат ячейки
ws1.Cells[row,col].Style.Numberformat.Format ="dd.MM.yyyy";//Вставляем распознанное значение в формате, заданном в предыдущей строчке
ws1.Cells[row,col].Value = dt;}elseif(int.TryParse(table1.GetCell(col-startColT1, row-startRowT1),out i)){
ws1.Cells[row,col].Style.Numberformat.Format ="0";
ws1.Cells[row,col].Value = i;}elseif(double.TryParse(table1.GetCell(col-startColT1, row-startRowT1),out d)){
ws1.Cells[row,col].Style.Numberformat.Format ="0.00";
ws1.Cells[row,col].Value = d;}else//Если не распознали - записываем в общем формате
ws1.Cells[row,col].Value = table1.GetCell(col-startColT1, row-startRowT1);}}
Получилось слегка посложнее, но зато теперь у нас корректно будут записываться данные.
8. Отформатируем полученную табличку в более приглядный вид. Стили таблиц аналогичны тем, которые можно увидеть в Excel, только английскими названиями. «Light1» соответствует «Светлый1», «Medium1» – «Средний1», «Dark1» – «Темный1». Конкретно для первого листа я посчитал подходящим стиль «Светлый19».
C#:
//Определяем диапазон области данныхExcelRange rangeT1 = ws1.Cells[startRowT1, startColT1, table1.RowCount+startRowT1-1, table1.ColCount+startColT1-1];//Определяем этот диапазон как таблицуExcelTable tableT1 = ws1.Tables.Add(rangeT1, ws1.Name.Replace(" ",String.Empty));//Задаём стиль таблицы. Стили аналогичны стилям в Excel, только названия на английском
tableT1.TableStyle = TableStyles.Light19;//Отключаем заголовки и фильтр, в нашем случае они не нужны
tableT1.ShowFilter =false;
tableT1.ShowHeader =false;
9. Переходим ко второму листу. По аналогии вставляем в него данные из второй таблицы.
По уму, конечно, стоит оформлять подобные вещи в метод/процедуру, но у нас сейчас задача показать именно работу с функционалом библиотеки.
Для разнообразия выберем немного иной формат даты.
10. Как вы могли заметить, в нарисованных заголовках второго листа был последний столбец под названием «Всего», и для него я не создал данных для заполнения. Рассмотрим такую ситуацию, что в ячейки этого столбца нужно получить суммы чисел для каждой из строк.
Для этого мы воспользуемся формулами – иными словами, зададим столбцу формулу, как мы это обычно делаем в Excel.
C#:
//Определяем диапазон ячеек, в которой будет работать формулаExcelRange formulaRange = ws2.Cells[startRowT2,table2.ColCount+startColT2,table2.RowCount+startRowT2-1,table2.ColCount+startColT2];//Задаём в диапазоне саму формулу. Формулы пишутся как в самом Excel (англ. версии), только без знака "="
formulaRange.Formula = String.Format("SUM(B{0}:I{0})", startRowT2);
formulaRange.Calculate();
Библиотека поддерживает большинство других формул Excel, единственное, рекомендуется их писать в английском варианте и без знака «=».
11. По аналогии с первым листом делаем форматирование области данных, теперь только уже вместе со столбцом «Всего». Дополнительно для последнего включаем особое форматирование.
C#:
ExcelRange rangeT2 = ws2.Cells[startRowT2, startColT2, table2.RowCount+startRowT2-1, table2.ColCount+startColT2];ExcelTable tableT2 = ws2.Tables.Add(rangeT2, ws2.Name.Replace(" ",String.Empty));
tableT2.TableStyle = TableStyles.Light16;
tableT2.ShowFilter =false;
tableT2.ShowHeader =false;
tableT2.ShowLastColumn =true;//Для последнего столбца ("Всего") дополнительно включаем особый стиль
12. Сохраняем полученный файл в папку проекта, называем его Result.xlsx.
C#:
Byte[] bin = exPack.GetAsByteArray();string resPath = project.Directory +@"\Result.xlsx";
File.WriteAllBytes(resPath, bin);
project.SendInfoToLog("Сохранили итоговый Excel-файл по адресу: "+resPath,true);
Вот, собственно, и всё. После выполнения такого сниппета в папке с проектом появится итоговый файл. В тестовом проекте для этой статьи получаем такие таблички.
Здравствуйте!
Есть в Эксель обединение смежных строк, смежных столбцов. Но Зеннопостер предпочитает сохранять в формате csv даже если в формате xls. Как бы сохранять csv или xls с указанием на объединенные строки или объединенные столбцы?
Пробовал прописывать параметрыдля строк и столбцов (row=3;col=3). Примерно так.
Какой есть способ, чтобы дополнительно не прописывать такое?
Как-то может использовать открый формат подобие xls, а потом пересохранить в xls?
Здравствуйте!
Есть в Эксель обединение смежных строк, смежных столбцов. Но Зеннопостер предпочитает сохранять в формате csv даже если в формате xls. Как бы сохранять csv или xls с указанием на объединенные строки или объединенные столбцы?
Пробовал прописывать параметрыдля строк и столбцов (row=3;col=3). Примерно так.
Какой есть способ, чтобы дополнительно не прописывать такое?
Как-то может использовать открый формат подобие xls, а потом пересохранить в xls?
Приветствую!
Честно говоря пока не очень понял, какие и с какой целью объединять столбцы/строки. Не могли бы привести конкретный пример, по типу "вот такую-то таблицу имеем, а надо получить вот такую-то" (т.е. примеры файлов с абсолютно любыми тестовыми данными).
А в общих чертах - если нужно объединение ячеек ровно как в Excel, то действительно придётся делать через внешние dll, по типу как в этой статье. Если же по известному принципу нужно объединить целиком какие-то определённые строки или столбцы - лучше делать встроенным функционалом Zenno, формат файла как правило тут не должен создавать проблем.
Приветствую!
Честно говоря пока не очень понял, какие и с какой целью объединять столбцы/строки. Не могли бы привести конкретный пример, по типу "вот такую-то таблицу имеем, а надо получить вот такую-то" (т.е. примеры файлов с абсолютно любыми тестовыми данными).
А в общих чертах - если нужно объединение ячеек ровно как в Excel, то действительно придётся делать через внешние dll, по типу как в этой статье. Если же по известному принципу нужно объединить целиком какие-то определённые строки или столбцы - лучше делать встроенным функционалом Zenno, формат файла как правило тут не должен создавать проблем.
Название публикации - Красивые отчеты в Эксель. Как красивые отчеты могут быть без объединения столбцов или строк. Пример простейший из Эксель вот такой - без ввода данных каких-либо.
Название публикации - Красивые отчеты в Эксель. Как красивые отчеты могут быть без объединения столбцов или строк. Пример простейший из Эксель вот такой - без ввода данных каких-либо.
В этом случае да, надо использовать стороннюю dll. Если говорить о той, которая используется в этой статье, то примерно так должно работать, если брать в пример ваш скриншот:
C#:
// Так
ws1.Cells["B2:C2"].Merge =true;
ws1.Cells["E4:E9"].Merge =true;// Или так
ws1.Cells[2,2,2,3].Merge =true;
ws1.Cells[4,5,9,5].Merge =true;
В этом случае да, надо использовать стороннюю dll. Если говорить о той, которая используется в этой статье, то примерно так должно работать, если брать в пример ваш скриншот:
C#:
// Так
ws1.Cells["B2:C2"].Merge =true;
ws1.Cells["E4:E9"].Merge =true;// Или так
ws1.Cells[2,2,2,3].Merge =true;
ws1.Cells[4,5,9,5].Merge =true;
В этом случае да, надо использовать стороннюю dll. Если говорить о той, которая используется в этой статье, то примерно так должно работать, если брать в пример ваш скриншот:
C#:
// Так
ws1.Cells["B2:C2"].Merge =true;
ws1.Cells["E4:E9"].Merge =true;// Или так
ws1.Cells[2,2,2,3].Merge =true;
ws1.Cells[4,5,9,5].Merge =true;