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-библиотеки, но на всякий случай разберём под спойлером по шагам.
Переходим к основным действиям. В первую очередь, создаём кубик C#-кода, в который поместим весь описанный ниже код.
1. Получаем внутренние таблицы проекта, предварительно заполненные нужными данными (которые спарсили/сгенерировали/получили из БД/ещё от куда-либо).
C#:
//Получаем временные таблицы с нужными данными
var table1 = project.Tables["Таблица 1"];
var table2 = project.Tables["Таблица 2"];
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 = new FileInfo(project.Directory + @"\Template.xlsx");
if (!template.Exists){ //Делаем проверку - если Template.xlsx отсутствует - выходим по красной ветке
project.SendErrorToLog("Упс! Файл Excel-шаблона 'Template.xlsx' отсутствует в директории проекта.", true);
return null;
}
5. Создаём объект нашего Excel-документа на базе Template.xlsx. Отныне весь дальнейший код будем писать внутри данных фигурных скобок.
C#:
using (ExcelPackage exPack = new ExcelPackage(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;
}else if (int.TryParse(table1.GetCell(col-startColT1, row-startRowT1), out i)){
ws1.Cells[row,col].Style.Numberformat.Format = "0";
ws1.Cells[row,col].Value = i;
}else if (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. Переходим ко второму листу. По аналогии вставляем в него данные из второй таблицы.
По уму, конечно, стоит оформлять подобные вещи в метод/процедуру, но у нас сейчас задача показать именно работу с функционалом библиотеки.
Для разнообразия выберем немного иной формат даты.
C#:
for (int row = startRowT2; row < table2.RowCount+startRowT2; row++){
for (int col = startColT2; col < table2.ColCount+startColT2; col++){
if (DateTime.TryParse(table2.GetCell(col-startColT2, row-startRowT2), out dt)){
ws2.Cells[row,col].Style.Numberformat.Format = "d MMM yy";
ws2.Cells[row,col].Value = dt;
}else if (int.TryParse(table2.GetCell(col-startColT2, row-startRowT2), out i)){
ws2.Cells[row,col].Style.Numberformat.Format = "0";
ws2.Cells[row,col].Value = i;
}else if (double.TryParse(table2.GetCell(col-startColT2, row-startRowT2), out d)){
ws2.Cells[row,col].Style.Numberformat.Format = "0.00";
ws2.Cells[row,col].Value = d;
}else
ws2.Cells[row,col].Value = table2.GetCell(col-startColT2, row-startRowT2);
}
}
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. По аналогии с первым листом делаем форматирование области данных, теперь только уже вместе со столбцом «Всего». Дополнительно для последнего включаем особое форматирование.
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;