Важное объявление о переносе форумов
  • Привет, Гость!
  • Войти
  • Регистрация
  • Записи
  • Форумы
  • Люди
  • Файлы
  • Работа
  • Технологии

MS Office >> Open Office = Отчеты без велосипеда

Все форумы  Поиск  Правила  Помощь 
 Активные темы  Темы без ответов
Привет, гость! Войти
Форумы GotDotNet.Ru » Office System » MS Office >> Open Office = Отчеты без велосипеда
Страницы: 1
RSS
MS Office >> Open Office = Отчеты без велосипеда
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#1
0
23.10.2007 9:48
Добрый день!

Очень долго решал классическую задачу. В текстовом/вордовом шаблоне расставить теги, а затем заменить их на значения дернутых из бд и тп. Хочу поделиться опытом, возможно предварив многие аналогичные вопросы и блуждания по инету. Статью писать времени не хватает поэтому решил просто выложить здесь код.

ЗЫ С Word и тп завязал, тк надоели грабли со слиянием, жуткие тормоза, и дикая структура документа, котор естественно, закрыта.

ЗЗЫ Смысл решения след. В odt файле расставляются текстовые теги типа <#column_name#>, в метод кидается DataRow и если находится столбец, то он заменяется тег заменяется значением. Причем это делается напрямую с файлом, не открывая тяжеловесных систем (типа ворда :-P).

Я не любитель открытого кода и тп. Но

  1. Но когда разобрался с open office, для меня было открытием, что .odt файлы это просто xml архивы и структура как на ладони.
  2. И естественно никакого гемора с лицензиями и тп.
  3. Скорость на порядок. Аналогичное решение открывалось в ворде до нескольких минут %). Здесь же стало открываться практически мгновенно.

Выдираю код из проекта, поэтому не особо причесан для понимания O:-)

using System;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.Zip;

namespace MyNamespace
{
    public static class WordWrapper
    {
        const int ERROR_FILE_NOT_FOUND = 2;
        const int ERROR_ACCESS_DENIED = 5;


        public static string GetEndFileName(string CurPath, string Alias)
        {
            return Path.Combine(CurPath, Alias + @".odt");
        }

        static readonly FastZip fz = new FastZip();
        public static string OpenWordDoc(string Alias, string TemplateName, string CurPath, IViewerEventArgs eArgs)
        {
            string endFilePath = GetEndFileName(CurPath, Alias + "_" + eArgs.CurDataRow["contract_name"]).Replace("/", "-");
            

            if (File.Exists(endFilePath))
            {
                DialogResult dr =
                    MessageBox.Show(string.Format("'{0}' существует открыть его?\n\nДА - откроет существующий\n\nНЕТ - создаст новый файл + ДАТА_СОЗДАНИЯ!", Alias)
                    , "Внимание!"
                    , MessageBoxButtons.YesNoCancel
                    , MessageBoxIcon.Warning
                    , MessageBoxDefaultButton.Button1);

                if (dr == DialogResult.Yes)
                {
                    return OpenExistingDoc(endFilePath);
                }
                else if (dr == DialogResult.No)
                {
                    endFilePath = GetEndFileName(CurPath, Alias + "_" + eArgs.CurDataRow["contract_name"] + "_" + DateTime.Now.ToString("yyyyMMddhhmm"));
                }
                else if (dr == DialogResult.Cancel)
                {
                    return "";
                }
            }

            if (!Directory.Exists(CurPath))
            {
                try
                {
                    Directory.CreateDirectory(CurPath);
                }
                catch (Exception exc)
                {
                    MessageBox.Show(exc.Message);
                    return "";
                }
            }

            //currow = eArgs.CurDataRow;
            string tempDir = Path.Combine(Environment.GetEnvironmentVariable("Temp"), Guid.NewGuid().ToString());
            string tempContentFileName = Path.Combine(tempDir, @"content.xml");
            //string tempFileName = GetEndFileName(tempDir, Alias);

            Cursor.Current = Cursors.WaitCursor;
            try
            {
                PrepareTempDir(tempDir);

                fz.ExtractZip(TemplateName, tempDir, "");

                byte[] bytes = File.ReadAllBytes(tempContentFileName);

                string str = Encoding.UTF8.GetString(bytes);
                str = FindAndReplace(str, eArgs.CurDataRow);

                File.WriteAllBytes(tempContentFileName, Encoding.UTF8.GetBytes(str));

                fz.CreateEmptyDirectories = true;
                fz.CreateZip(endFilePath, tempDir, true, "");

                //File.Copy(tempFileName, endFilePath);
            }
            catch(Exception ee)
            {
                MessageBox.Show(ee.ToString());
                return string.Empty;
            }
            finally
            {
                Directory.Delete(tempDir, true);
                Cursor.Current = Cursors.Default;
            }

            OpenExistingDoc(endFilePath);
            
            return endFilePath;
        }

        private static void PrepareTempDir(string tempDir)
        {
            if(Directory.Exists(tempDir))
            {
                Directory.Delete(tempDir, true);
            }
            Directory.CreateDirectory(tempDir);
        }

        static readonly Regex rx = new Regex(p1, ro);
        static readonly Regex rx2 = new Regex(p2, ro);

        const string p1 = @"<\#(([\s]*<[^>]+>)+(?<red_select>[^<#]+)?)+\#>";
        const string p2 = @"<\#\w+\#>";

        const RegexOptions ro = RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled;

        private static string FindAndReplace(string xml, DataRow currow)
        {
            MatchEvaluator e1 = delegate(Match m)
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < m.Groups["red_select"].Captures.Count; i++)
                {
                    sb.Append(m.Groups["red_select"].Captures[i].Value);
                }
                string clmnName = sb.ToString();
                if (clmnName.Length > 0 && currow.Table.Columns.Contains(clmnName))
                {
                    return currow[clmnName].ToString();
                }
                return "Ошибка";
            };
            
            xml = rx.Replace(xml, e1);

            e1 = delegate(Match m)
                     {
                         string clmnName =
                             m.Value.Substring("<#".Length, (m.Value.Length) - ">#".Length - "<#".Length);
                         if (clmnName.Length > 0 && currow.Table.Columns.Contains(clmnName))
                         {
                             return currow[clmnName].ToString();
                         }
                         return "Ошибка";
                     };

            return rx2.Replace(xml, e1);
        }

        public static string OpenExistingDoc(string file)
        {
            try
            {
                Process.Start(file);
            }
            catch (Win32Exception e)
            {
                if (e.NativeErrorCode == ERROR_FILE_NOT_FOUND)
                {
                    MessageBox.Show(e.Message + ". Необходимо проверить путь к файлу. Обратитесь к администратору!");
                }

                else if (e.NativeErrorCode == ERROR_ACCESS_DENIED)
                {
                    MessageBox.Show(e.Message +
                                    ". У вас не хватает разрешений для доступа к файлу. Обратитесь к администратору!");
                }
            }
            return file;
        }
        
    }


}



ЗЗЫЫ Буду рад если это кому либо поможет сэкономить месяцы поисков и кучу выброшенного кода.

С/у Дмитрий.
 
 
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#2
0
29.10.2007 18:39
PS По идее можно расширить пример закладками, что может дать еще повышения производительности. Но есть минус закладки не видны и дожны быть уникальны.
С/у Дмитрий.
 
 
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#3
0
28.03.2008 11:04
А вот статья как это сделать на жабе
http://www.i-rs.ru/Stat-i/Java-OpenOf...r-otchetov
С/у Дмитрий.
 
 
webb
Сообщений: 1099 Регистрация: 09.07.2005
#4
0
28.03.2008 12:47
а неужели для этой задачи не подходят специализированные инструменты вроде crystal reports? я не спец в этой области, просто интересуюсь на будущее
 
 
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#5
0
28.03.2008 12:56
Практически во всех отчетных системах отсутствует возможность редактировать полученный отчет. Конечно, можно выгрузить отчет в опр. файл (ворд или ексель). Но как правило, съезжает вся структура. А если даже не съезжает, то возникает др проблема: текст выгружается в виде набора текстбоксов, а уж редактировать такой документ это такой гемор даже для опытных пользователей.
Чего только стОит добавить строку в таблице.

Другая сложность это формирование отчетов в виде многостраничных договоров и тп. Тот еще гемор.
С/у Дмитрий.
 
 
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#6
0
25.10.2008 11:10
Переработал пример: Добавил обработку табличных частей и добавление рисунков (например, печати и подписей (-.-)). Также существует использование сервиса по созданию отчета.

Используется 2 файла OODocCreator.cs и MyFuncEval.cs. Подразумевается использование класса ProgramConstMngr, который вадает путь к хранилищу файлов и к шаблонам.

С/у Дмитрий.
 
 
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#7
0
25.10.2008 11:11
OODocCreator.cs :

using System;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Skip.DALLib.ProgramConstMngr;
using ICSharpCode.SharpZipLib.Zip;

namespace OfficeWrapperLib
{
    public static class OODocCreator
    {
        #region Consts

        const string pBookMark = @"{[\w\s;()]*}";

        private const string pDtl = @"{BeginTable}(.*?\s*?)*{EndTable}";
        private const string pWorkRow = @"<table:table-row>(.*?\s*?)*</table:table-row>";

        private const string pImage = @"<draw:frame.+?(?<ImageBookMark>{Image\((?<field_name>\w+)\)})+?[\s\S]+?</draw:frame>";

        //private const string pImage = @"<draw:frame.+?({[\w\s;()]*})+?[\s\S]+?</draw:frame>";

        private const string pImagePath = @"xlink:href=""Pictures/(?<newfile_name>[\w.]+)""";

        static readonly Regex rxBookMark = new Regex(pBookMark, RgxOptions);

        private static readonly Regex rxDtl = new Regex(pDtl, RgxOptionsMulty);
        private static readonly Regex rxWorkRow = new Regex(pWorkRow, RgxOptions);
        private static readonly Regex rxImage = new Regex(pImage, RgxOptions);
        private static readonly Regex rxImagePath = new Regex(pImagePath, RgxOptions);

        const RegexOptions RgxOptions = RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled;
        const RegexOptions RgxOptionsMulty = RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled;

        #endregion

        static OODocCreator()
        {
            var programConstMngr = new ProgramConstMngr();
            StoragePath = programConstMngr.GetStoragePath();
            TemplatePathDir = programConstMngr.GetTemplatePath();
        }

        public static readonly string StoragePath;
        public static readonly string TemplatePathDir;

        public static string GetEndFileName(string Alias, int ParentViewerID, int? keyVal)
        {
            string CurPath = Path.Combine(StoragePath, ParentViewerID + @"\" + keyVal + @"\");

            return Path.Combine(CurPath, Alias + @".odt").Replace("/", "-");
        }

        static readonly FastZip fz = new FastZip();

        public static string PrepareDoc(string Alias, int ParentViewerID, int? keyVal, DataSet RPDataSet)
        {
            string endFilePath = GetEndFileName(Alias, ParentViewerID, keyVal);
            if (File.Exists(endFilePath))
            {
                endFilePath = Path.Combine(Path.GetDirectoryName(endFilePath), Path.GetFileNameWithoutExtension(endFilePath))
                    + "_" + DateTime.Now.ToString("yyyyMMddhhmm") + Path.GetExtension(endFilePath);
            }

            var TemplateFileName = Path.Combine(TemplatePathDir, Alias + @".odt");

            var directoryName = Path.GetDirectoryName(endFilePath);
            if (!Directory.Exists(directoryName))
            {
                Directory.CreateDirectory(directoryName);
            }


            string tempBaseDir = //Path.Combine(Path.GetDirectoryName(TemplateFileName), "templTemp");
                        GetTemplatePath();

            if (string.IsNullOrEmpty(tempBaseDir)) return "";

            string tempDir = Path.Combine(tempBaseDir, Guid.NewGuid().ToString());

            if (RPDataSet.Tables.Count < 1 || RPDataSet.Tables[0].Rows.Count < 1)
            {
                File.Copy(TemplateFileName, endFilePath);
                return endFilePath;
            }

            DataRow CurDataRow = RPDataSet.Tables[0].Rows[0];

            //Cursor.Current = Cursors.WaitCursor;

            try
            {
                CreateTempDir(tempDir);

                string tempContentFileName = Path.Combine(tempDir, @"content.xml");
                string str = LoadOOContent(tempDir, TemplateFileName, tempContentFileName);

                str = ProcessDetail(RPDataSet, str);

                str = FindAndReplace(str, CurDataRow);

                string ImageDir = Path.Combine(TemplatePathDir, "Pictures");
                ProcessImage(tempDir, str, CurDataRow, ImageDir);

                SaveOOContent(tempDir, tempContentFileName, str, endFilePath);
            }
            finally
            {
                Directory.Delete(tempDir, true);
                //Cursor.Current = Cursors.Default;
            }

            return endFilePath;
        }

        private static string GetTemplatePath()
        {
            return Environment.GetEnvironmentVariable("Temp");
        }

        
        private static string ProcessDetail(DataSet RPDataSet, string str)
        {
            if (RPDataSet.Tables.Count == 2)
            {
                var lastTbIndex = RPDataSet.Tables.Count - 1;
                DataTable tb = RPDataSet.Tables[lastTbIndex];
                str = FindAndReplaceDetail(str, tb);
            }

            return str;
        }

        private static void SaveOOContent(string tempDir, string tempContentFileName, string str, string endFilePath)
        {
            File.WriteAllBytes(tempContentFileName, Encoding.UTF8.GetBytes(str));

            fz.CreateEmptyDirectories = true;
            fz.CreateZip(endFilePath, tempDir, true, "");
        }

        private static string LoadOOContent(string tempDir, string TemplateName, string tempContentFileName)
        {
            fz.ExtractZip(TemplateName, tempDir, @"");

            byte[] bytes = File.ReadAllBytes(tempContentFileName);

            return Encoding.UTF8.GetString(bytes);
        }

        private static void ProcessImage(string tempDir, string str, DataRow CurDataRow, string ImageDir)
        {
            if (!IsExistImage(str)) return;

            string destImageDir = Path.Combine(tempDir, "Pictures");

            if (!Directory.Exists(destImageDir))
            {
                Directory.CreateDirectory(destImageDir);
            }

            foreach (Match mImage in rxImage.Matches(str))
            {
                string ImageClmnName = mImage.Groups["field_name"].Value;
                var ImageFile = (string)CurDataRow[ImageClmnName];

                string NewImageFile = rxImagePath.Matches(mImage.Value)[0].Groups["newfile_name"].Value;

                CopyImageToOOReport(ImageFile, NewImageFile, ImageDir, destImageDir);
            }
        }

        private static void CopyImageToOOReport(string ImageFile, string NewImageFile, string ImageDir, string destImageDir)
        {
            string sourceFileName = Path.Combine(ImageDir, ImageFile);
            string destFileName = Path.Combine(destImageDir, NewImageFile);

            File.Copy(sourceFileName, destFileName, true);
        }

        private static bool IsExistImage(string str)
        {
            return rxImage.IsMatch(str);
        }

        private static string FindAndReplaceDetail(string xml, DataTable tb)
        {
            MatchEvaluator meDtl = delegate(Match mDtl)
            {
                bool IsWorkRow = false;

                MatchEvaluator meWorkRow = delegate(Match mWorkRow)
                {
                    if (IsWorkRow) return mWorkRow.Value;

                    if (rxBookMark.IsMatch(mWorkRow.Value))
                    {
                        IsWorkRow = true;
                        string workRow = mWorkRow.Value;

                        var sb = new StringBuilder();
                        foreach (DataRow row in tb.Rows)
                        {
                            sb.AppendLine(FindAndReplace(workRow, row));
                        }
                        return sb.ToString();
                    }

                    return mWorkRow.Value;
                };

                string replace = rxWorkRow.Replace(mDtl.Value, meWorkRow);

                return replace.Replace("{BeginTable}", "").Replace("{EndTable}", "");
            };

            return rxDtl.Replace(xml, meDtl);
        }

        private static void CreateTempDir(string tempDir)
        {
            if(Directory.Exists(tempDir))
            {
                Directory.Delete(tempDir, true);
            }
            Directory.CreateDirectory(tempDir);
        }

        private static string FindAndReplace(string xml, DataRow currow)
        {
            MatchEvaluator meAll =
                delegate(Match m)
                    {
                        string resultStr = MyFuncEval.CalcFunc(m.Value, currow, currow.Table.DataSet.Tables[1]);
                        return resultStr;
                    };

            return rxBookMark.Replace(xml, meAll);
        }
        
    }
}



С/у Дмитрий.
 
 
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#8
0
25.10.2008 11:13
MyFuncEval.cs: там возможна обработка простейших формул Sum, Format  и тыды

using System;
using System.Data;
using System.Text.RegularExpressions;

namespace OfficeWrapperLib
{
    public static class MyFuncEval
    {
        public static string CalcFunc(string Func, DataRow currow, DataTable tb)
        {
            string variant = Func;
            while (IsFunc(variant))
            {
                variant = CalcSimpleFunc(variant, currow, tb);
                if (Func == variant) // не обработал
                {
                    return variant;
                }
            }

            return IsDBVal(variant) ? CalcDBVal(variant, currow) : variant;
        }

        private static readonly Regex rxDBVal = new Regex(@"{(?<clmn_name>\w+)}", RgxOptions);
        private static string CalcDBVal(string variant, DataRow currow)
        {
            MatchEvaluator me = delegate(Match match)
                                    {
                                        string clmnName = match.Groups["clmn_name"].Value;
                                        bool isExistsClmn = clmnName.Length > 0 &&
                                                            currow.Table.Columns.Contains(clmnName);
                                        if (isExistsClmn)
                                        {
                                            return currow[clmnName].ToString();
                                        }

                                        return match.Value;
                                    };

            return rxDBVal.Replace(variant, me);
        }

        private static bool IsDBVal(string variant)
        {
            return rxDBVal.IsMatch(variant);
        }

        //private static Dictionary<string, Func<string, string[], string>> FuncList;

        public static string EvaluateImageFunc(string Func)
        {
            MatchEvaluator me = match => match.Groups["func_body"].Value;

            return rxSimpleFunc.Replace(Func, me);
        }

        const RegexOptions RgxOptions = RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled;
        private static readonly Regex rxSimpleFunc = new Regex(@"{?(?<func_name>\w+)\((?<func_body>[^(^)]*)\)}?", RgxOptions);
        private static string CalcSimpleFunc(string Func, DataRow currow, DataTable tb)
        {
            MatchEvaluator me = delegate(Match match)
                                    {
                                        string func_name = match.Groups["func_name"].Value;
                                        string[] funcParams = SplitParams(match.Groups["func_body"].Value);

                                        switch (func_name.ToUpper())
                                        {
                                            case "ROWNUM":
                                                return (currow.Table.Rows.IndexOf(currow) + 1).ToString();
                                            case "FORMAT":
                                                var formatType = funcParams[1];

                                                var varParam = funcParams[0];

                                                decimal val;
                                                if (decimal.TryParse(varParam, out val))
                                                {
                                                    return val.ToString(formatType);
                                                }

                                                string clmnName = varParam;
                                                bool isExistsClmn = clmnName.Length > 0 && currow.Table.Columns.Contains(clmnName);
                                                if (isExistsClmn)
                                                {
                                                    object dbVal = currow[clmnName];
                                                    if (Convert.IsDBNull(dbVal)) return "";

                                                    if (dbVal is DateTime)
                                                    {
                                                        return Convert.ToDateTime(dbVal).ToString(formatType);
                                                    }
            
                                                    return Convert.ToDecimal(dbVal).ToString(formatType);
                                                }

                                                return "";

                                            case "SUM":
                                                decimal sum = 0;
                                                string columnName = funcParams[0];
                                                foreach (DataRow row in tb.Rows)
                                                {
                                                    sum += (decimal)row[columnName];
                                                }
                                                return sum.ToString();

                                            default:
                                                return match.Value;
                                        }
                                    };
            return rxSimpleFunc.Replace(Func, me);
        }

        private static readonly Regex rxFuncParams = new Regex(@";\s*", RgxOptions);
        private static string[] SplitParams(string FuncBody)
        {
            return rxFuncParams.Split(FuncBody);
        }

        private static readonly Regex rxIsFunc = new Regex(@"{?(\w+)\(.*\)}?", RgxOptions);
        private static bool IsFunc(string variant)
        {
            return rxIsFunc.IsMatch(variant);
        }
    }
}



С/у Дмитрий.
 
 
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#9
0
25.10.2008 11:29
ЗЫ формать расстановки теперь следующий {clmn_name}

Чтобы вставить изображение (дернутое из бд). Используется формат {Image(stamp_name)}, где stamp_name - название столбца с изображением. Таблицы обрамляются тегами {BeginTable}..{EndTable}, чтобы отличить Detail таблицы от других. В таблице создается шаблон строки, которая затем множится. В таблице можно использовать значения с формулами: {format(mc_count; F2)}, например.

Сложности с которыми сейчас столкнулся:

  1. Реализация группировки.
  2. Перенос шапки на другие страницы.
  3. Определение количество попавших строк на страницу (например для подсчета итога по странице, для злосчастного Торга 12).

Буду предельно благодарен за идеи.

Если кому-то понадобиться, то могу попробовать реализовать рабочий пример.

С/у Дмитрий.
 
 
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#10
0
19.01.2009 9:45
2. Пункт решил нехитрым способом.
В 3 опенофисе(ворде) появилась галка "Повторять заголовок/Первые ХХ строки".
С/у Дмитрий.
 
 
Vadem
Сообщений: 161 Регистрация: 06.04.2008
#11
0
14.02.2011 11:10
Я в своё время такое делал только для ворда и через xslt.
Там как-то попроще было.
Там просто ворд в xml сохранялся(docx стати тоже архив).
И структура у этого xml кстати тоже открытая.
А потом xsl преобразованием что надо заменялось.
Правда там без картинок было, но думаю тоже можно сделать.
 
 
Димон
Сообщений: 1679 Регистрация: 12.03.2004
#12
0
10.05.2011 17:50
1. Сравните размер файлов МС и ОО по размеру.
2. Добавил кроме картинок формирование штрихкодов на документах, глянул в МС там тоже рисунки в папке.
3. Docx. Что делать с теми у кого 2003 офис (имхо даж ща таких большинство)?
4. В ОО есть очень удобная функция отправить как Word/PDF, которой манагеры активно пользуются.
5. Odt и тп ща признаны стандартами на уровне страны.
6. Ну про 400 баков (или хз скока он там ща) за МС Офис на нос я ваще молчу.
Так что для нас этот вариант (ОО) безальтернативен. В чем прикол Использования МС Офиса для экономической системы мне сложно понять.
Да сталкивался с такими моментами как 200 страничные документы с макросами и жестким форматированием, но в том случае стоимость отчета покрывала стоимость лицензии на офис. Пожалуйста. Для определенных задач и инструменты соответствующие. Но разводить Заказчика на доп лицензии на офис для того что напечатать односложные отчеты - это не для нас.

ЗЫ Честно гря мой механизм не сильно привязан к структуре файла, т.е я спокойно использую для текстовых файлов и тп.
Наверняка небольшие танцы с бубнами и система заработает с МС Офисом. Но танцевать с обратной совместимостью: чур меня.
Благодаря данному решению мы всей организацией перешли на ОО. Причем 80% пользователей так и не заметило подмены.
С/у Дмитрий.
 
 
andrucci
Сообщений: 4 Регистрация: 23.03.2009
#13
0
18.05.2011 17:21
Заманчиво выглядит. Может, выложишь демку?
 
 
repon
Сообщений: 128 Регистрация: 09.01.2006
#14
0
09.06.2011 15:27
я тоже от примера-демки не отказался быы)
 
 
repon
Сообщений: 128 Регистрация: 09.01.2006
#15
0
10.06.2011 9:25
хотя бы пример кода, работы с этими классами (
 
 
enrod
Сообщений: 2 Регистрация: 23.06.2011
#16
0
23.06.2011 15:14
Димон, не совсем понятно, что подставлять со стороны DataSet.
В шаблоне файла я поставил {Fullname}

При вызове метода подставляю такой вот DataSet:

System.Data.DataSet ds = new DataSet();

        // Create a new DataTable.
        DataTable table = new DataTable("Column_Names");
        DataColumn column;
        DataRow row;
        
        column = new DataColumn();
        column.DataType = System.Type.GetType("System.String");
        column.ColumnName = "Fullname";
        column.AutoIncrement = false;
        column.Caption = "Fullname";
        column.ReadOnly = false;
        column.Unique = false;

        table.Columns.Add(column);
        row = table.NewRow();
        row["Fullname"] = "Лазарь Иванович";
        table.Rows.Add(row);
        
        ds.Tables.Add(table);

        string str = OODocCreator.PrepareDoc("OdtTest", 0, null, ds);   


Что я делаю не так? Что-то никак не получается разобрать и понять, где же в вашем классе идет проверка на имя колонки и подстановка значения.
 
 
enrod
Сообщений: 2 Регистрация: 23.06.2011
#17
0
24.06.2011 12:12
Всё, разобрался. И сразу же нашел причину проблемы.
 
 
andrucci
Сообщений: 4 Регистрация: 23.03.2009
#18
0
28.06.2011 12:54
Народ, гляньте это: AODL - the .Net module of the ODFToolkit. Работает на ура
 
 
 
Страницы: 1
Форумы GotDotNet.Ru » Office System » MS Office >> Open Office = Отчеты без велосипеда
О сайте   Свяжитесь с нами   Версия для печати
Работает на .NET Forge CMS  |  Хостинг на Parking.Ru