alexvw Ответов: 2

Многоместный документ rdlc из XML файла


Всем привет,

Я могу успешно генерировать и заполнять отчет rdlc (документ типа счета-фактуры {ТЕРМИНАЛЬНОЕ ОБОРУДОВАНИЕ}) из xml-файла с помощью набора данных.

Этот rdlc имеет различные разделы, некоторые требуют отдельных полей, а некоторые требуют матриц. Пока все идет хорошо!

Вот пример такого xml файла:

<?xml version="1.0" encoding="ISO-8859-1"?>
<SetDTE>
<DTE version="1.0" >
<Documento ID="MiPE76266617-2495">
    <Encabezado>
    	...
    </Encabezado>
    <Detalle>
    	...
    </Detalle>
</DTE>
</SetDTE>

и вот как я назначаю/заполняю каждый источник данных:
RepVwer.LocalReport.DataSources.Clear();
RepVwer.LocalReport.DataSources.Add(new ReportDataSource("Documento", dsXML.Tables[0]));
RepVwer.LocalReport.DataSources.Add(new ReportDataSource("Emisor", dsXML.Tables[1]));
RepVwer.LocalReport.DataSources.Add(new ReportDataSource("Receptor", dsXML.Tables[2]));
RepVwer.LocalReport.DataSources.Add(new ReportDataSource("IdDoc", dsXML.Tables[3]));


Ситуация такова, что эти xml-файлы теперь могут иметь более одного документа; т. е.
целые идентичные структуры узлов (дочерние), где каждая из них представляет собой документ {ТЕРМИНАЛЬНОЕ ОБОРУДОВАНИЕ}.

Пример:

<?xml version="1.0" encoding="ISO-8859-1"?>
<SetDTE>
<DTE version="1.0" >
<Documento ID="MiPE76266617-720">
    <Encabezado>
    	...
    </Encabezado>
    <Detalle>
			...
    </Detalle>
    <Detalle>
			...
    </Detalle>
</DTE>
<DTE version="1.0" >
<Documento ID="MiPE76266617-2495">
    <Encabezado>
    	...
    </Encabezado>
    <Detalle>
    	...
    </Detalle>
</DTE>
</SetDTE>


Как я могу переписать rdlc, чтобы приспособиться к такому сценарию? Он должен дублировать всю структуру (отдельные поля и матрицы) для каждого документа.

Я заметил, что в этом сценарии каждая таблица в наборе данных имеет поле ID, которое помогает идентифицировать/связать связанные записи между таблицами данных.

Что я уже пробовал:

Я искал в интернете инсайты, но пока не нашел ничего подходящего (не совсем уверен, что искать). 2018/01/09 :: до сих пор кажется, что вложенные матрицы работают только тогда, когда все данные содержатся в одном источнике данных; поскольку у меня есть несколько источников данных, возможно, будет невозможно достичь того, что я ищу.

Я пытался использовать элемент управления списком, но до сих пор не смог понять, как работать с группами, внутренними матрицами и т. д.

Заранее благодарю вас всех за Ваш вклад!.

2018/01/09 16:54 (UTC -04:00) :: После еще нескольких исследований я наткнулся на то, как объединить таблицы данных (в первый раз). Такой подход позволил мне успешно объединить большинство объектов datatable в большой on, что, в свою очередь, позволило мне установить стандартную сгруппированную матрицу для отображения статических полей каждого документа.

Однако мне не удалось интегрировать таблицы данных с подробными данными {n записей для каждого документа}. предложения?

2 Ответов

Рейтинг:
8

alexvw

Всем привет,

Я смог придумать рабочее решение; однако, если у кого-то есть лучшее, остальные из нас, безусловно, будут признательны, чтобы узнать об этом.

Случай:
Заполните rdlc из xml-файла, содержащего 1-n дочерних объектов, имеющих как статические, так и динамические данные.

Примерная Структура

<?xml version="1.0" encoding="ISO-8859-1"?>
<SetDTE>
<DTE version="1.0" > <!-- Children {1-n} (node of interest) -->
<Documento ID="MiPE76266617-720">
    <Encabezado> <!-- static data = single group -->
    	... 
    </Encabezado>
    <Detalle> <!-- dynamic data = 0-n groups -->
	... 
    </Detalle>
    <Detalle>
	...
    </Detalle>
</DTE>
<DTE version="1.0" >
<Documento ID="MiPE76266617-2495">
    <Encabezado> <!-- static data = single group -->
    	...
    </Encabezado>
    <Detalle> <!-- dynamic data = 0-n groups -->
    	...
    </Detalle>
</DTE>
</SetDTE>


Сначала я попытался заполнить его с помощью стандартного отчета множеством таблиц данных, сгенерированных набором данных, загруженным из исходного xml-файла:

string xmlSource = System.IO.File.ReadAllText(DTEPath);

DataSet dsXML = new DTE(xmlSource);


Где ТЕРМИНАЛЬНОЕ ОБОРУДОВАНИЕ это настраиваемый класс, наследующий от DataSet, который использует свой метод ReadXml для заполнения объекта. Затем я извлекаю необходимые таблицы из источника и добавляю их в базу:

base.Tables.Add(dsXML.Tables["Documento"] == null ? new Documento() : dsXML.Tables["Documento"].Copy());


Где Мы это настраиваемый класс, который наследуется от datatable, цель которого состоит в том, чтобы обеспечить согласованную структуру, если источник не имеет ожидаемого узла. Такой подход допустим, но только для xml-файлов с одним узлом "интереса".

Когда вы сталкиваетесь с xml-файлами с несколькими узлами "интереса", стандартный отчет не сокращает его. Я попытался применить элемент управления списком или вложенные матрицы, но они не только требуют одного источника данных, но и детализируют строки, допускающие только статические данные.

Временное решение я нашел, было:
один) Объедините все статические таблицы данных в одну с помощью установки соответствующих первичных ключей (метод, который я проигнорировал и смог реализовать благодаря эта должность).

б) Создание и применение вложенных отчетов для обработки динамических областей.

Процедура:
1) Создайте базовый отчет, включающий таблицу(табликс), которая должна быть настроена так, чтобы иметь столько строк группы, сколько необходимо. В этом случае основная группа и дочерняя группа; я расширил одну строку/столбец, оставленные в табликсе, чтобы охватить всю область тела отчета.

2) В эту единственную ячейку добавлены все необходимые текстовые поля, прямоугольники, линии и т. д. для выделения статических данных, то есть данных, которые имеют уникальные значения для каждой строки группы. (Прямоугольники, которые я добавил, являются заполнителями для необходимых вложенных отчетов)

3) Построил вложенные отчеты (мне нужно было два) и обязательно добавил к ним необходимый входной параметр и фильтр. В этом случае каждый вложенный отчет имеет источник данных и соответствующую таблицу для размещения его значений.

4) Добавил вложенные отчеты к основному; каждый внутри своего назначенного прямоугольника.

5) код:

один) Форма размещения (winform); должна связывать обработчик событий, необходимый для обработки вложенного отчета(ов):

private void FrmMain_Load(object sender, EventArgs e) 
        {
            .... //unrelated code
            RepVwer.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(SetSubDataSource);

        }

б) Основная пустота: которая получает данные, настраивает элемент управления ReportViewer и запускает визуализацию отчета:

private void LoadXmlDTE(string DTEPath)
        {
            try
            {
                DataSet dsXML = new DTE(System.IO.File.ReadAllText(DTEPath));
                
                RepVwer.ProcessingMode = ProcessingMode.Local;
                RepVwer.LocalReport.ReportEmbeddedResource = "DTEViewer.rdlc.EncabezadoDTE.rdlc";
                RepVwer.LocalReport.DataSources.Clear();

                //Datos estáticos por documento
                DataTable auxData = GenerateStaticGlobalData(dsXML);
                RepVwer.LocalReport.DataSources.Add(new ReportDataSource("Global", auxData));
                
                //Datos dinámicos por documento {Sub-Reportes}
                _detalle = dsXML.Tables[6];
                _referencia = dsXML.Tables[7];
                
                this.RepVwer.RefreshReport();

                //... irrelevant code
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, "...", "...", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

с) Метод GenerateStaticGlobalData-это метод, отвечающий за объединение всех статических таблиц данных в одну, которая будет основным источником данных отчета:
private DataTable GenerateStaticGlobalData(DataSet dsXML)
       {
           DataTable auxData = dsXML.Tables[0].Copy();

           auxData.PrimaryKey = new DataColumn[] { auxData.Columns["Documento_Id"] }; //Documento_Id {0}
           dsXML.Tables[1].PrimaryKey = new DataColumn[] { dsXML.Tables[1].Columns["Documento_Id"] };
           auxData.Merge(dsXML.Tables[1]);

           auxData.PrimaryKey = new DataColumn[] { auxData.Columns["Encabezado_Id"] }; //Encabezado_Id {4}
           for (int i = 2; i < 6; i++)
           {
               dsXML.Tables[i].PrimaryKey = new DataColumn[] { dsXML.Tables[i].Columns["Encabezado_Id"] };
               auxData.Merge(dsXML.Tables[i]);
           }

           return auxData; //output
       }

Примечание Я был в состоянии использовать для оператор в приведенном выше коде, потому что мой класс DTE организовал эти таблицы данных в таком порядке.

д) Давайте не будем забывать о том, что обработчик событий назначает источник(ы) данных для вложенного отчета(ов):
public void SetSubDataSource(object sender, SubreportProcessingEventArgs e)
       {
           e.DataSources.Add(new ReportDataSource("Detalle", _detalle));
           e.DataSources.Add(new ReportDataSource("Referencias", _referencia));
       }


Вот и все; теперь у меня есть отчет (с двумя интегрированными вложенными отчетами), который может быть представлен на экране, как и ожидалось клиентом; то есть документ на страницу, который они могут либо экспортировать, либо распечатать по желанию.

Надеюсь, это может быть полезно для кого-то еще.

Еще раз спасибо всем, кто нашел время прочитать мой вопрос, а теперь и мой собственный ответ.


Рейтинг:
0

Dirk Bahle

Я написал статью в .Net/VB.Net, которая может быть полезна для чтения XML-ваших данных в A .Чистая модель/преобразуйте модель и делайте с ней все, что хотите:

Чтение и запись XML в C#/VB.Net[^]

Вы не найдете эту статью через поиск, потому что она сосредоточена на древовидных структурированных данных, но ваш вопрос звучит так, как будто вы смотрите на что - то похожее на древовидные структурированные данные, так что это чтение может быть полезно-надеюсь, это поможет, Дирк


alexvw

Привет Дирк,

Я просмотрел статью, хотя она кажется довольно обширной с точки зрения чтения/записи xml-данных, она проливает свет на мой вопрос о построении rdlc и заполнении его с помощью вложенных матриц из нескольких наборов данных.

В любом случае большое спасибо; я ценю вашу готовность помочь.