Подтвердить что ты не робот

Лучший способ просмотра таблицы с * лотами * столбцов?

Рискуя быть сбитым с толку, я хочу спросить, какой лучший механизм (лучше всего, очевидно, субъективен для нарушения правил, присущий здесь) для просмотра данных из таблицы с использованием С# с большим количеством столбцов. Во многом я имею в виду что-то вроде 1000.

Теперь, прежде чем вы получите весь клик счастливым или выбросите ответы типа "почему, черт возьми, у вас когда-нибудь будет стол с таким количеством столбцов", позвольте мне сказать, что это фактически часть требования к дизайну. Мы собираем данные так быстро, как можем, из 1000 точек данных. Нам нужно хранить их как можно быстрее, отсюда и плоский стол. Данные должны быть доступны непосредственно из SQL Server, поэтому база данных (мы используем SQL Compact с таблицей-direct).

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

Я пробовал сетку данных. Он запутывается, потому что (неудивительно) он не предназначен для обработки множества столбцов.

Я попытался использовать средство просмотра в Studio. Он запускается после 256, плюс конечный пользователь не будет устанавливать Studio в любом случае.

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

Соответствующая (или полунаправленная) информация:

  • Таблица имеет 1000 столбцов (читайте выше, прежде чем получать клик счастливым)
  • Использование SQL Compact версии 3.5
  • Работа на рабочем столе
  • Поиск ответа с управляемым кодом
4b9b3361

Ответ 1

Хорошо, то, что оказалось правильным ответом для меня, это использовать ReportViewer control, но никоим образом не задокументирован в MSDN. Проблема в том, что у меня есть динамические данные, поэтому мне нужен динамический отчет, и все учебные пособия и т.д., Похоже, предполагают, что у вас есть роскошь знать все во время разработки, чтобы вы могли указать и щелкнуть свой путь через Мастер.

В итоге решение получило пару штук. Во-первых, мне пришлось создать код для динамического генерации RDLC, который использует ReportViewer для описания макета отчета и того, какие поля данных сопоставляются с чем. Вот что я придумал:

public static Stream BuildRDLCStream(
    DataSet data, string name, string reportXslPath)
{
  using (MemoryStream schemaStream = new MemoryStream())
  {
    // save the schema to a stream
    data.WriteXmlSchema(schemaStream);
    schemaStream.Seek(0, SeekOrigin.Begin);

    // load it into a Document and set the Name variable
    XmlDocument xmlDomSchema = new XmlDocument();
    xmlDomSchema.Load(schemaStream);        
    xmlDomSchema.DocumentElement.SetAttribute("Name", data.DataSetName);

    // load the report XSL file (that the magic)
    XslCompiledTransform xform = new XslCompiledTransform();
    xform.Load(reportXslPath);

    // do the transform
    MemoryStream rdlcStream = new MemoryStream();
    XmlWriter writer = XmlWriter.Create(rdlcStream);
    xform.Transform(xmlDomSchema, writer);
    writer.Close();
    rdlcStream.Seek(0, SeekOrigin.Begin);

    // send back the RDLC
    return rdlcStream;
  }
}

Вторая часть - это XSL файл, который я взял сразу после блог Dan Shipe. Код RDLC там был совершенно бесполезным, поскольку он был предназначен для использования в Интернете, но XSL - это чистое золото. Я поставил его в нижней части этого сообщения для полноты, если блог когда-либо выходит в автономный режим.

Как только у меня эти две части, это просто вопрос создания формы с элементом управления ReportViewer, а затем с помощью этого бита кода для его настройки:

ds.DataSetName = name;

Stream rdlc = RdlcEngine.BuildRDLCStream(
    ds, name, "c:\\temp\\rdlc\\report.xsl");

reportView.LocalReport.LoadReportDefinition(rdlc);
reportView.LocalReport.DataSources.Clear();
reportView.LocalReport.DataSources.Add(
    new ReportDataSource(ds.DataSetName, ds.Tables[0]));
reportView.RefreshReport();

Ключевым моментом здесь является то, что 'ds' - это объект DataSet с единым DataTable в нем с данными, которые будут отображаться.

Опять же, для полноты, вот XSL - извините за размер:

    <?xml version="1.0"?>
    <!-- Stylesheet for creating ReportViewer RDLC documents -->
    <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxsl="urn:schemas-microsoft-com:xslt"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
      xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner"  xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition"
      >

     <xsl:variable name="mvarName" select="/xs:schema/@Name"/>
     <xsl:variable name="mvarFontSize">8pt</xsl:variable>
     <xsl:variable name="mvarFontWeight">500</xsl:variable>
     <xsl:variable name="mvarFontWeightBold">700</xsl:variable>


     <xsl:template match="/">
      <xsl:apply-templates select="/xs:schema/xs:element/xs:complexType/xs:choice/xs:element/xs:complexType/xs:sequence">
      </xsl:apply-templates>
     </xsl:template>

     <xsl:template match="xs:sequence">
      <Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition">
       <BottomMargin>1in</BottomMargin>
       <RightMargin>1in</RightMargin>
       <LeftMargin>1in</LeftMargin>
       <TopMargin>1in</TopMargin>
       <InteractiveHeight>11in</InteractiveHeight>
       <InteractiveWidth>8.5in</InteractiveWidth>
       <Width>6.5in</Width>
       <Language>en-US</Language>
       <rd:DrawGrid>true</rd:DrawGrid>
       <rd:SnapToGrid>true</rd:SnapToGrid>
       <rd:ReportID>7358b654-3ca3-44a0-8677-efe0a55c7c45</rd:ReportID>

       <xsl:call-template name="BuildDataSource">
       </xsl:call-template>

       <xsl:call-template name="BuildDataSet">
       </xsl:call-template>

       <Body>
        <Height>0.50in</Height>
        <ReportItems>
         <Table Name="table1">
          <DataSetName><xsl:value-of select="$mvarName" /></DataSetName>
          <Top>0.5in</Top>
          <Height>0.50in</Height>
          <Header>
           <TableRows>
            <TableRow>
             <Height>0.25in</Height>
             <TableCells>

              <xsl:apply-templates select="xs:element" mode="HeaderTableCell">
              </xsl:apply-templates>

             </TableCells>
            </TableRow>
           </TableRows>
          </Header>
          <Details>
           <TableRows>
            <TableRow>
             <Height>0.25in</Height>
             <TableCells>

              <xsl:apply-templates select="xs:element" mode="DetailTableCell">
              </xsl:apply-templates>

             </TableCells>
            </TableRow>
           </TableRows>
          </Details>
          <TableColumns>

           <xsl:apply-templates select="xs:element" mode="TableColumn">
           </xsl:apply-templates>

          </TableColumns>
         </Table>
        </ReportItems>
       </Body>
      </Report>
     </xsl:template>

     <xsl:template name="BuildDataSource">
      <DataSources>
       <DataSource Name="DummyDataSource">
        <ConnectionProperties>
         <ConnectString/>
         <DataProvider>SQL</DataProvider>
        </ConnectionProperties>
        <rd:DataSourceID>84635ff8-d177-4a25-9aa5-5a921652c79c</rd:DataSourceID>
       </DataSource>
      </DataSources>
     </xsl:template>

     <xsl:template name="BuildDataSet">
      <DataSets>
       <DataSet Name="{$mvarName}">
        <Query>
         <rd:UseGenericDesigner>true</rd:UseGenericDesigner>
         <CommandText/>
         <DataSourceName>DummyDataSource</DataSourceName>
        </Query>
        <Fields>

         <xsl:apply-templates select="xs:element" mode="Field">
         </xsl:apply-templates>

        </Fields>
       </DataSet>
      </DataSets>
     </xsl:template>

     <xsl:template match="xs:element" mode="Field">
      <xsl:variable name="varFieldName"> 
       <xsl:value-of select="@name" />
      </xsl:variable>

      <xsl:variable name="varDataType">
       <xsl:choose>
        <xsl:when test="@type='xs:int'">System.Int32</xsl:when>
        <xsl:when test="@type='xs:string'">System.String</xsl:when>
        <xsl:when test="@type='xs:dateTime'">System.DateTime</xsl:when>
        <xsl:when test="@type='xs:boolean'">System.Boolean</xsl:when>
       </xsl:choose>
      </xsl:variable>

      <Field Name="{$varFieldName}">
       <rd:TypeName><xsl:value-of select="$varDataType"/></rd:TypeName>
       <DataField><xsl:value-of select="$varFieldName"/></DataField>
      </Field>
     </xsl:template>

     <xsl:template match="xs:element" mode="HeaderTableCell">
      <xsl:variable name="varFieldName"> 
       <xsl:value-of select="@name" />
      </xsl:variable>

      <TableCell>
       <ReportItems>
        <Textbox Name="textbox{position()}">
         <rd:DefaultName>textbox<xsl:value-of select="position()"/>
         </rd:DefaultName>
         <Value><xsl:value-of select="$varFieldName"/></Value>
         <CanGrow>true</CanGrow>
         <ZIndex>7</ZIndex>
         <Style>
          <TextAlign>Center</TextAlign>
          <PaddingLeft>2pt</PaddingLeft>
          <PaddingBottom>2pt</PaddingBottom>
          <PaddingRight>2pt</PaddingRight>
          <PaddingTop>2pt</PaddingTop>
          <FontSize><xsl:value-of select="$mvarFontSize"/></FontSize> 
          <FontWeight><xsl:value-of select="$mvarFontWeightBold"/></FontWeight> 
          <BackgroundColor>#000000</BackgroundColor> 
          <Color>#ffffff</Color>
          <BorderColor>
           <Default>#ffffff</Default>
          </BorderColor>
          <BorderStyle>
           <Default>Solid</Default>
          </BorderStyle>
         </Style>
        </Textbox>
       </ReportItems>
      </TableCell>
     </xsl:template>

     <xsl:template match="xs:element" mode="DetailTableCell">
      <xsl:variable name="varFieldName"> 
       <xsl:value-of select="@name" />
      </xsl:variable>

      <TableCell>
       <ReportItems>
        <Textbox Name="{$varFieldName}">
         <rd:DefaultName><xsl:value-of select="$varFieldName"/></rd:DefaultName>
         <Value>=Fields!<xsl:value-of select="$varFieldName"/>.Value</Value>
         <CanGrow>true</CanGrow>
         <ZIndex>7</ZIndex>
         <Style>
          <TextAlign>Left</TextAlign>
          <PaddingLeft>2pt</PaddingLeft>
          <PaddingBottom>2pt</PaddingBottom>
          <PaddingRight>2pt</PaddingRight>
          <PaddingTop>2pt</PaddingTop>
          <FontSize><xsl:value-of select="$mvarFontSize"/></FontSize> 
          <FontWeight><xsl:value-of select="$mvarFontWeight"/></FontWeight> 
          <BackgroundColor>#e0e0e0</BackgroundColor> 
          <Color>#000000</Color> 
          <BorderColor>
           <Default>#ffffff</Default> 
          </BorderColor>
          <BorderStyle>
            <Default>Solid</Default>
          </BorderStyle>
         </Style>
        </Textbox>
       </ReportItems>
      </TableCell>
     </xsl:template>

     <xsl:template match="xs:element" mode="TableColumn">
      <TableColumn>
       <Width>0.75in</Width>
      </TableColumn>
     </xsl:template>

     <xsl:template name="replace-string">
      <xsl:param name="text"/>
      <xsl:param name="from"/>
      <xsl:param name="to"/>
      <xsl:choose>
       <xsl:when test="contains($text, $from)">
        <xsl:variable name="before" select="substring-before($text, $from)"/>
        <xsl:variable name="after" select="substring-after($text, $from)"/>
        <xsl:variable name="prefix" select="concat($before, $to)"/>
        <xsl:value-of select="$before"/>
        <xsl:value-of select="$to"/>
        <xsl:call-template name="replace-string">
         <xsl:with-param name="text" select="$after"/>
         <xsl:with-param name="from" select="$from"/>
         <xsl:with-param name="to" select="$to"/>
        </xsl:call-template>
       </xsl:when>
       <xsl:otherwise>
        <xsl:value-of select="$text"/>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    </xsl:stylesheet>

Ответ 2

Если вы собираетесь реализовать свой собственный пользовательский элемент управления, вы можете сделать сетку Fisheye следующим образом:

ссылка мертвого образа

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

Обновление: Silverlight имеет один из этих, по-видимому. Сортировка.

Ответ 3

Вы можете форматировать все числа в виде n-символьных строк с пробелами, а затем отображать их в шрифте с фиксированной шириной.

1       2       3       4       6      36     436    6346
2       3       4       6      36     436    6346       0
3       4       6      36     436    6346       3       4
4       6      36     436    6346     333     222     334

Ответ 4

Как хранить данные в файле csv, что даст вам возможность просматривать. Если у вашего пользователя есть excel или Open Office Calc, они могут легко импортировать данные (не уверены, существует ли ограничение по столбцу для Calc, но excel 2007 может содержать 16384 столбца) и просматривать его через эту программу?

Ответ 5

Вам нужно просмотреть несколько строк в одной таблице?

Я предполагаю, что эти данные численные, есть ли способ показать отдельные данные в виде сетки 20 * 50 или что-то в этом роде, а затем просто разбивать страницы на строки?

Например, строка 1, столбец 1 = номер 1 базы данных, строка 2, столбец 1 = столбец 21 базы данных и т.д.

Id = 1
     1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
----|--------------------------------------------------------
  0 |  
 20 |  
 40 |
 60 |
 80 |
100 |
120 |
etc |

Ответ 6

попробуйте таблицу html с очень маленьким шрифтом

Если вы обеспокоены форматированием таблицы, используйте CSS:

td { font-size: 0.2em; text-align: right; }

поочередно, если все ваши номера имеют одинаковый размер, вы также можете просто сгенерировать отображение "стена номеров", например. используйте шрифт с фиксированной шириной и отобразите столбцы шириной 5 символов на панели прокрутки.

Ответ 7

Это немного зависит от того, насколько она должна быть. Если это всего лишь инструмент проверки отладки/определения места, вы можете поместить несколько DataGrids бок о бок, каждый из которых отображает выбор столбцов. Было бы уродливо, но было бы работоспособным.

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

Ответ 8

DataGrid (или даже ListView) должен иметь возможность обрабатывать таблицу с 32 столбцами и 32 строками, что позволит вам отображать сразу всю ценность данных в строке базы данных. Это позволит вам мгновенно увидеть, не хватает ли некоторых ячеек данных или нет.

Ответ 9

Я чувствую себя грязным даже для того, чтобы предположить это, но вы могли бы сделать что-то вроде:

SELECT Field1 + ' - ' + Field2 + ... AS EvilMegaColumn FROM Table

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

Ответ 10

Кто прочитает 1000 столбцов таблицы??? Попытайтесь придумать способ фильтрации или визуализации данных.

Ответ 11

Возможно, вам следует исследовать базу данных другого типа. Я слышал, что базы данных, ориентированные на столбцы, хороши для такого рода вещей (тогда как типичная RDBMS ориентирована на ряд). Кроме того, если вы не вернетесь к обновлению строк после их первого вставки, возможно, бинарный плоский файл будет лучше, чем гигантская таблица?

Ответ 12

Я бы сделал это разворачиванием. На первой странице (или в верхней части страницы) у вас будут элементы управления, которые выбирают строку. На следующей странице (или внизу страницы) вы увидите данные из выбранной строки. В зависимости от требуемой ширины ячейки вы можете сделать это как 100 строк из 10 столбцов или 1000 строк из 1 столбца, например.

Это было бы довольно легко сделать как динамический клиентский javascript - вы даже могли бы сделать его редактируемым таким образом. Я не уверен, как это будет работать на С#.

Ответ 13

Если вы только после проверки, вы не можете проверить каждое поле программно и сообщить, что вся строка в порядке!. Тогда вам понадобится очень простая сетка данных, в которой перечислены строки, которые не так хороши.

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

Ответ 14

Находясь наклонно, я бы спросил, нужно ли пользователю одновременно загружать все столбцы?

Если пользователи будут рады отобразить подмножество столбцов одновременно (скажем, 100 за раз или выборочные настройки за раз), я бы использовал некоторую сетку данных (встроенный в один, или ListView, или, возможно, сторонний), чтобы отобразить подмножество, с CheckedListView, состыкованным сбоку, позволяя отображать подмножество интересов.

В качестве альтернативы вы можете отобразить какие-то сводные данные, показывающие count/average/xxx для групп из 100 столбцов?

Ответ 15

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

  • Ваш SQL может разрешить определять 1000 столбцов.
  • Строка SQL не может превышать ограничение байта строки.

Каждая реализация базы данных имеет размер страницы (4k/8k), и одна строка должна соответствовать этому размеру данных. NULL обычно бесплатны. Это означает, что 1000 ints 1000 x 4 байта будут просто соответствовать размеру страницы 4k.

Если вы говорите данные с varchars, тогда проблема хуже. Сколько символов в каждом столбце? Сколько столбцов можно заполнить? Если у вас в среднем 10 символов, а размер вашей страницы - 8k, вы теряете данные с ошибкой SQL.

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

Ответ 16

.., чтобы проверить, действительно ли данные там находятся.

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

Цвет пикселя зависит от данных. Он может быть черно-белым для пустых/данных. Или это может быть цвет, чтобы показать, что стоимость растет или уменьшается с каждой строкой. Или красный для внезапных скачков данных. Все аномалии, которые вы могли нормально ловить глазами в сетке данных.

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

Просто нажмите, чтобы вернуться к карте пикселей.

Ответ 17

Учитывая, что пользователю все равно придется прокручивать по горизонтали, вы можете использовать обычную сетку данных, показывающую разумное количество столбцов (скажем, 50). Затем у вас есть горизонтальная полоса прокрутки, расположенная под сеткой, которая выбирает поднабор столбцов для отображения. Когда полоса прокрутки находится слева, вы показываете столбцы 1-50, когда вы нажимаете стрелку вправо, вы переходите к 2-51 и т.д.

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

Ответ 18

Сколько данных имеет решающее значение для исходного представления? Я вижу, что вы делаете что-то вроде сетки типа master/detail, где вы кладете критические столбцы (например, 10) на datagrid, и когда пользователь нажимает на просмотр деталей, вы можете взять оставшиеся столбцы и отобразить их в "область свойств" или что-то в этом отношении.

Ответ 19

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

Затем вы можете выполнить итерацию при подсчете не по умолчанию /total, чтобы показать процент.

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

Ответ 20

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

Другой вариант - прочитать данные и создать из него огромный статический набор html-страниц. Затем вы можете вызвать браузер из своей программы, чтобы просмотреть его.

Ответ 21

Прокрутите панель и покажите 10 столбцов за раз (они могут быть загружены или кэшированы или что вам нужно). Когда вы прокручиваетесь влево, покажите первую десятку. По мере прокрутки вправо отобразите последнюю последовательность столбцов. Таким образом, всего лишь 10 столбцов активны в любой заданной точке. По-моему, попытка отображать 1000 столбцов будет каким-то другим способом. PS: Это не более чем идеальное предположение; Я не уверен, возможно ли это возможно.