Коллекция подобъектов в виде столбцов в таблице переменных столбцов - PullRequest
0 голосов
/ 27 сентября 2018

У меня есть БД, которая представляет информацию о повторном заполнении.Компания A получает счет-фактуру и разделяет его на компании A, B, C.

Для каждого входящего счета-фактуры нам необходимо создать документ для повторного расчета.

Созданная мной база данных имеет следующие характеристики:

  • У документа есть идентификатор, другая информация (описание, дата счета-фактуры, ...)
  • Он имеет переменное количество строк, по одной для каждой из исходных строк счета-фактуры.
  • Имеет переменное число столбцов, для компаний счет будет разделен.
  • Каждая строка в одном и том же документе имеет одинаковое количество столбцов.

Это разделенное представление БД:

+-----------------+   +------------------+   +--------------------+
| DOCUMENTS       +   | ROWS             |   | COLS               |
+-----------------+   +------------------+   +--------------------+
| DocID        PK |1-*| DocID         PK |1-*| DocID           PK |   +-----------------+
| ...             |   | Row           PK |1-*| Row             PK |   | COMPANIES       |
+-----------------+   | Description      |   | Col             PK |   +-----------------+ 
                      | RebillAmount     |   | CompanyID          |*-1| CompanyID    PK |
                      +------------------+   | RebilledAmount     |   | Description     |
                                             +--------------------+   +-----------------+

Что япопытка получить представление в виде таблицы, например:

+-----------------+--------------+-------------+-------------+-------------+
| Description     | RebillAmount | "Company A" | "Company B" | "Company C" | ...
+-----------------+--------------+-------------+-------------+-------------+
| ISP invoice     |   € 1.000,00 |    € 333,00 |    € 333,00 |    € 334,00 |
| Insurance       |     € 600,00 |      € 0,00 |    € 400,00 |    € 200,00 | 
| ...             |              |             |             |             |
+-----------------+--------------+-------------+-------------+-------------+

Данные извлекаются с использованием Linq to SQL.

Я успешно создал DataGridView, вручную перебирая строки и столбцы, используя словарьдля отслеживания столбцов:

Dim CompanyCols as new Dictionary(Of Integer, DataGridViewColumn)

Dim DocID = 1
Dim Doc = (From d In dc.Documents Where f.DocID = DocID Select d).Single

For Each r In Doc.Rows
    Dim rowid = Grid.Rows.Add()
    Dim row = Grid.Rows(rowid)
    row.Cells(ColEnum.Description).Value = r.Description
    riga.Cells(ColEnum.RebillAmount).Value = r.RebillAmount
    Dim col As DataGridViewColumn
    For Each c In r.Cols
        If CompanyCols.ContainsKey(c.CompanyID) Then
            col = CompanyCols(c.CompanyID)
        Else
            Dim newcol = New DataGridViewTextBoxColumn With {.HeaderText = c.Companies.Description}
            col = Grid.Columns(Grid.Columns.Add(newcol))
            CompanyCols.Add(c.CompanyID, col)
        End If
        row.Cells(col.Index).Value = c.RebillAmount
    Next
Next

К сожалению, этот подход разрывает связь с объектами базы данных, поэтому, если мне нужно отредактировать данные и сохранить их, мне нужно отсканировать всю сетку и вручную обновить объект «Док»и его подобъектов.

Есть ли способ "привязать" строки к Doc.rows и столбцы к Doc.cols?

Спасибо!

1 Ответ

0 голосов
/ 27 сентября 2018

Итак, у вас есть коллекция документов.Вы хотите отобразить один документ в таблице.Столбцы в таблице представляют Companies, которые упоминаются в документе.Разные документы могут иметь разное количество компаний.

К счастью, вы хотите, чтобы в вашей таблице отображался только один документ: получив документ, вы знаете, какие компании следует добавить в виде столбцов в таблицу.

Хотя вы определили это водин документ в каждой строке имеет одинаковое количество столбцов , и поэтому в каждом документе используется одинаковое количество компаний, вы не указали, что в каждой строке используются одни и те же компании.

может закончиться так:

Rows[0] has two Cols:
    Cols[0] has Company[0]
    Cols[1] has Company[1]
Rows[1] has two Cols:
    Cols[0] has Company[0]
    Cols[1] has Company[2]
Rows[3] has two Cols:
    Cols[0] has Company[3]
    Cols[1] has Company[4]

Если я посмотрю на ваш код, в этом случае вы захотите показать 5 столбцов.

Row        Company[0]   Company[1]  Company[2]   Company[3]  Company[4]
----------------------------------------------------------------------------
Row[0]       aaa           bbb
Row[1]       ccc                       ddd
Row[2]                                               eee         fff

Каждый столбец компании в вашей таблице имеет столбецЗаголовок, который показывает название компании.Если у вас есть строка, значения ячеек строки будут либо нулевыми, если компания не используется строкой, либо RebilledAmount ячейки, в которой используется компания, имя которой указано в заголовке столбца.

Это означает, что как только вы получите свой документ, вам нужно будет знать все используемые компании.Каждая компания становится одной колонной.В каждой колонке вам нужно помнить название компании и идентификационный номер компании

. Для каждой строки, которую вы хотите добавить, вам нужно будет найти столбец, который соответствует идентификаторам компаний.которые используются Cols этой строки.

Мой Visual Basic немного заржавел, поэтому я покажу вам код на C #.Я уверен, что вы сможете понять идею и перевести ее на Visual Basic

Document fetchedDocument = ...

// find out which companies are used by the Document.
// from every company remember the name and the Id:
var companyInfo = fetchedDocument.Rows      // take all rows
    .SelectMany(row => row.Cols)            // from these rows take all Cols
    .Select(col => new
    {
         CompanyId = col.CompanyId,         // from every Col take the CompanyId
         Name = col.Company.Name,           // and the company name
    })  
    .Distinct();                            // remove duplicates

Если вы не получили CompanyNames при загрузке документа, вам придется их извлечь вотдельный запрос.Если у вас есть названия компаний где-то локально, в Словаре или что-то еще, найдите их потом:

var companyIds = fetchedDocument.Rows        // take all rows
    .SelectMany(row => row.Cols)             // from all rows take the Cols
    .Select(col => col.CompanyId)            // from every col take the companyId
    .Distinct();                             // remove duplicates

// add the CompanyNames
var companyInfo = companyIds.Select(companyId => new
{
    Id = companyId,
    Name = CompanyCollection[companyId].CompanyName,
});

Как только вы знаете все компании, вы можете добавить все столбцы.Сначала мы добавим столбцы для Description и RebillAmount:

myDataGridView.Columns.Clear();

// Column Description:
int columnDescriptionIndex = myDataGridView.Columns.Add(new DataGridViewColumn()
{
    Name = "ColDescription",             // name of the column
    HeaderText = "Description",          // header text
    ValueType = typeof(string),          // this column shows strings
    DataPropertyName = "Description",    // this column shows property Description
});

// Column RebillAmount:
int columnRebillAmountIndex = myDataGridView.Columns.Add(new DataGridViewColumn()
{
    Name = "ColRebillAmount",             // name of the column
    HeaderText = "RebillAmount",          // header text
    DataPropertyName = "RebillAmount",    // this column shows property RebillAmount
    ValueType = typeof(decimal),          // this column shows decimals
    // if desired: add a DefaultCellStyle to define the display format of the amount
}

Теперь добавим столбцы компании.В каждом столбце компании вы должны помнить идентификатор отображаемой компании.Для этого мы создаем подкласс DataGridViewColumn, который содержит идентификатор отображаемой компании:

class CompanyColumn : DataGridViewColumn
{
    public int CompanyId {get; private set;}

    public CompanyColumn(int companyId, string companyName)
    {
        this.CompanyId = companyId;
        Name = companyName;               // name of the column
        HeaderText = companyName;         // header text
        ValueType = typeof(decimal);      // this column shows decimals
        // if desired: add a DefaultCellStyle to define the display format
    }
}

Добавить один столбец на используемую компанию;для быстрого поиска: поместите индекс столбца в словарь, ключ - companyId, значение columnIndex

var companyColumns = new Dictionary<int, int>()
foreach(var usedCompany in usedCompanies)
{
     var columnIndex = myDataGridView.Columns
         .Add(new CompanyColumn(usedCompany.Id, usedCompany.Name);
     companyColumns.Add(usedCompany.Id, columnIndex);
}

После добавления всех столбцов вы можете добавить строки:

myDataGridView.Rows.Clear();

foreach(var row in document.Rows)
{
    var addedRow = myDataGridView.AddRow();

    // Description and RebillAmount
    addedRow.Cells[colDescriptionIndex].Value = row.Description;
    addedRow.Cells[colRebillAmountIndex].Value = row.RebillAmount;

    // add the value for every company in the row, in the correct column
    foreach (var col in row.Cols
    {
        // every col has a companyId
        // find in the dictionary the index of the column that represents this company
        int columnIndex = companyColumns[col.CompanyId];

        // put the RebilledAmount in the column with the found index
        addedRow.Cells[columnIndex].Value = cell.RebilledAmount;
    }
}

Теперь, если ячейка изменяется, вы хотите изменить соответствующее значение в Документах:

void UpdateChangedCell(DataGridViewCell cell)
{
     if (cell.ColumnIndex == colDescriptionIndex)
     {    // the changed cell is a description cell
          string description = (string)cell.Value;
          document.Rows[cell.RowIndex].Description = description;
     }
     else if (cell.ColumnIndex == colRebillAmountIndex)
     {    // the changed cell is a rebillAmount cell
          decimal rebillAmount = (decimal)cell.Value;
          document.Rows[cell.RowIndex].RebillAmount = rebillAmount;
     }
     else
     {   // the changed cell is in one of the company columns:
         CompanyColumn column = (CompanyColumn)myDataGridView.Columns[cell.ColumnIndex];
          int companyId = column.CompanyId;
          decimal rebilledAmount = (decimal)column.Value;

          // update the one and only Col in this Row that has CompanyId
          var colToUpdate = row.Cols
              .Where(col => col.CompanyId == companyId)
              .Single();
          colToUpdate.RebilledAmount = rebilledAmount;
     }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...