C#. Построение и сохранение таблиц

Статус: Offline
Реєстрація: 14.09.2005
Повідом.: 951
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #1
C#. Построение и сохранение таблиц

Здравствуйте. Встала такая задача: необходимо создавать таблицу, с заголовками столбцов и строк. Количество строк и столбцов варьируется, так же как и размер заголовка. После того, как получена таблица, её необходимо сохранять в файл.
У меня было несколько вариантов решения:
1. Построение таблицы в текстовом виде. Я не нашёл вообще никаких описаний, по какому принципу строятся такие таблицы, а именно, как рассчитываются размеры ячеек в зависимости от заголовков и содержимого ячеек и как потом туда заносить данные.
2. Построение таблицы при помощи контрола tableLayoutPanel. Таблицу тут построить не проблема, но вот сохранить как следует не получается. Для сохранения нашёл только метод DrawToBitmap(). С его помощью таблица сохраняется как изображение, но при этом почему-то некоторые участки не прорисовываются (см. прикрепленное изображение)
3. Построение таблицы с помощью DataGridView. Тут тоже в принципе можно построить таблицу и все размеры можно автоматически подогнать. Сохраняется в изображение тоже нормально, но вот только не понятно, как сделать, чтобы сохранялась только таблица, а не вся область DataGridView.

Есть какие-нибудь идеи по поводу описанного мной или как-то по другому?
 

Вкладення

  • Таблица.png
    Таблица.png
    21.9 КБ · Перегляди: 1124
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #2
погодь, в каком виде тебе нужна таблица? в виде изображения?
почему бы не строить(рисовать) сразу в System.Drawing.Bitmap?
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #3
да, собственно файл этот для чего нужен?
позырить ради или надо потом загружать из него данные?
или ваще нужен экспорт в картинке?
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #4
Таблица нужна в нормальном виде и должна быть возможность получать из него изображение.. Если пробовать рисовать таблицу руками, то это будет кошмар.

Сохранение таблицы в файл необходимо для того, чтобы хранить результаты и при необходимости эту таблицу засунуть в документ и отправить на печать...
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #5
тогда не заморачивайся с изображениями, а сделай следующее:
1. отображай таблицу во что тебе удобно (DataGrid, ListView, ...)
2. когда встанет вопрос об отправке на печать, сгенерь какой-нибудь промежуточный HTML (с TABLE'ами, TR'ами, TD'шками и пр.) и отправь на печать его.

и проще и дешевле
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #6
+1 за экспорт в HTML.
сам так делаю там де таблицу надо "задокументировать".
и пофиг чем оно отбражается, ListView или еще чем..
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #7
HTML это, конечно, интересно, но изображение предпочтительнее, потому что, как я уже сказал, таблицы будут печататься не отдельно. Это будет скорее всего вордовский документ, отчёт, в который и нужно вставлять изображения..

Нашёл в чём проблема во время прорисовки графика из tableLayoutPanel. Как всегда и бывает, решение проблемы оказалось до отупения гениальным: такие глюки с прорисовкой из-за того, что по-умолчанию фон у таблицы стоит прозрачный. При изменении на любой нормальный цвет всё прорисовывается как надо... Всем спасибо за помощь!
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #8
нужно написать свой алгоритм, в котором и описать процесс выборки каких строк и столбцов тебе нужно, а не всё подряд
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #9
HTML это, конечно, интересно, но изображение предпочтительнее

а HTML на битмапку отрендерить и сохранить ее в нужном формате (jpg/gif/bmp/png и т.д.) религия не позволяет?

Если пользуешь первый фреймворк то в нем нет WebBrowser'а, его нужно импортить вручную. Начиная со второй версии компонент WebBrowser присутствует. Добавляешь обработчик OnDocumentComplete:
Код:
[Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
    ComVisible(true),
    ComImport]
interface IHTMLElementRender
{
    void DrawToDC([In] IntPtr hDC);
    void SetDocumentPrinter([In, MarshalAs(UnmanagedType.BStr)] string bstrPrinterName, [In] IntPtr hDC);
};

private void OnDocumentComplete(object sender, AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent e)
{
    IHTMLDocument2 document = (IHTMLDocument2) this.axWebBrowser1.Document;
    if (document != null)
    {
          IHTMLElement element = (IHTMLElement) document.body;
          if (element != null)
          {
              IHTMLElementRender render = (IHTMLElementRender) element;
              if (render != null)
              {
                    using(Bitmap bmp = new Bitmap(1024,768))
                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                          render.DrawToDC(g.GetHdc());
                          bmp.Save("MyTableImage.bmp");
                    }
              }
          }
    }
}

код скомпоновал, не тестил, но думаю смысл понятен, должно работать
 
Останнє редагування:
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #10
Я уже реализовал построение и сохранение таблиц через объект TableLayoutPanel
Через DataGridView знаю только использование метода DataGridView.DrawToBitmap(). Таблицу как раз и нужно сохранять целиком, но вот как делать выборку или сохранять отдельные наборы столбцов или строк - я не знаю

Опять таки, через TableLayoutPanel.DrawToBitmap() рендерит таблицу нормально и вызовом одной функции
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #11

да нахрен тебе та таблица сдалась? Тебе чтото в ней поменять надо будет и опять голову ломать будешь, вместо того чтобы в html пару тегов добавить
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #12
Не понял, что поменять, например? Таблица просто выводит набор полей из базы данных плюс при необходимости она сортируется и выводится процентные соотношения..
Чтобы изменить количество строк или столбцов достаточно изменить их число в соответствующем свойстве объекта. Добавление объекта в таблицу - .Add(объект, столбец, строка). Где тут ломать голову?
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #13

вот и подумай что будет проще поменять - таблицу в html'е или какойто уродливый объект. Впрочем делай как знаешь, пока человек на грабли не наступит так и не научится ничему
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #14
Конечно, объект.
В объекте:
Код:
tableLayoutPanel1.ColumnCount = NewColumnCount;
tableLayoutPanel1.RowCount = NewRowCount;

В html же это выглядит как добавление массы тэгов. Вообще html подразумевает разметку, нужно соответственно помимо всего прочего ещё думать о том, чтобы везде текст влазил. А в случае с tableLayoutPanel, размеры таблицы подгоняются автоматически.

Ну и где тут грабли? Или тут скорее "граблей бояться - в сарай не ходить"? Не вижу проблемы - уже почти как неделю всё сделано и работает и никаких проблем..

P.S. И, наконец, у меня есть таблица, которая строится прямо на форме. Пользователь на неё смотрит и если нужно - сохраняет. Так вот, нужно чтобы она выглядела точно так же как она построена и при сохранении из объекта это будет то же, что видит пользователь.. html будет выглядеть по-другому.
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #15
html - hyper text
он тоже свободно тянется, в зависимости от контента. Klez дело говорит.
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #16

дуракам закон не писан

html генерить нужно не тупым плюсованием тегов, а с умом - из DataSet'а. Например, я бы сделал так - кидаешь данные в DataSet, сохраняешь в XML, трансформируешь с помощью XSL в HTML. Грузишь в WebBrowser, из обработчика OnDocumentComplete рендеришь содержимое в битмапку и сохраняешь битмапку как bmp или jpeg на диск

Пользователю показывать можешь тот-же WebBrowser загрузив в него сгенеренный HTML. Все будет выглядеть один в один, т.к. будет использован один и тот-же рендерер...

Если надо подправить внешний вид - достаточно XSLT файло с шаблоном поправить. Никаких свойств и кривых объектов юзать не надо. Все автоматом рендерится, таблицы авторесайзятся как душе угодно и т.п. Оформление на любой вкус - все возможности HTML/CSS к вашим услугам

Если в дальнейшем появится необходимость сохранять например в PDF, добавляешь еще один XSL скрипт для трансформации в FO и цепляешь nFOP, которым процессишь FO в PDF

и это все - десять-двадцать строк на C#, все остальное - оформление рюшечек на HTML/CSS


а нефик "строить таблицы на форме"! Кладешь на форму WebBrowser, загружаешь в него сгенеренный HTML и все будет выглядеть 1 в 1, что в картинке, что на форме, что на принтере...
Более того, пользователь получает возможность копировать часть или всю таблицу в WORD или EXCEL, сохранять ее не только как bmp/jpeg, но и как HTML. И даже более того - в таблице можно будет использовать гиперссылки на другие таблицы и т.п. И для реализации этих возможностей не нужно дописывать ни одной строчки кода!

Ну и где тут грабли? Или тут скорее "граблей бояться - в сарай не ходить"?

лет через 5-10 поймешь
 
Останнє редагування:
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #17
кстати, рендер в битмап тут лишнее. не городите огород.
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #18
кстати, рендер в битмап тут лишнее. не городите огород.

вобщем-то да, я как-то упустил из виду что ТС-у сохранение картинки нужно было чтобы можно было в WORD/EXCEL вставлять. А раз это решается простым копированием. То и необходимость рендера в битмапку отпадает за ненадобностью...
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #19
Нет, я не спорю, может так и правильнее.. Но в первую очередь меня интересует вопрос: почему? Просто объясни. Конечно, можно переделать то, что уже работает, но чтобы начинать работать в этом направлении, необходима какая-то веская причина. Вот чем не устроили свойства и чем кривы эти объекты?

Я просто выбрал наиболее простой и понятный мне, опять таки, найденный мною способ реализовать функцию, чтобы было больше времени на более важный функционал. Метод с HTML кажется мне, как минимум, более сложным. Хотя, может быть, если бы я подробно разобрался что и как работает, моё мнение изменилось бы
 
  • 🔴 10:31 Повітряна тривога в Харків.обл.
  • #20

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