Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# Windows Forms
Войти
Регистрация
Восстановить пароль
 
Cha1000000
2 / 2 / 2
Регистрация: 04.06.2015
Сообщений: 204
Записей в блоге: 1
#1

Сохранение/чтение/работа с файлами Excel без вызова СОМ (альтернативные методы) - C#

11.05.2017, 09:35. Просмотров 717. Ответов 16
Метки нет (Все метки)

Добрый день, коллеги!
Столкнулся с такой проблемой: в проекте Windows Forms реализовал сохранение в Excel файл (в два формата) таким образом
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using Excel = Microsoft.Office.Interop.Excel;
 
namespace KKM_ProgBase_Utility
{
    public partial class fm_Main : Form
    {
        private Excel.Application ExcelApp;
        private Excel.Range excelcells;
 
        public fm_Main()
        {
            InitializeComponent();
        }
        
        private void mi_SaveToExcel_Click(object sender, EventArgs e)
        {//Сохранение в файлы Excel
            int i, j;
            saveTags.Title = "Экспорт в файл Excel";
            saveTags.Filter = "Файл Excel (*.xls) | *.xls |Файл Excel (*.csv) |*.csv";
 
            if (saveTags.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    Excel.Application ExcelApp = new Excel.Application();
                    Excel.Workbook workbook = ExcelApp.Workbooks.Add(Type.Missing);
                    Excel.Worksheet worksheet = workbook.ActiveSheet;
                    //Заголовок таблицы
                    for (j = 0; j < ProgTable.ColumnCount; j++)
                        ExcelApp.Cells[1, j + 1] = ProgTable.Columns[j].HeaderText;
                    //Данные
                    for (i = 0; i < ProgTable.Rows.Count; i++)
                    {
                        for (j = 0; j < ProgTable.ColumnCount; j++)
                        {
                            ExcelApp.Cells[i + 2, j + 1] = ProgTable.Rows[i].Cells[j].Value;
                        }
                    }
                    //////
                    ExcelApp.AlertBeforeOverwriting = false;
                    ExcelApp.DisplayAlerts = false; //Не запрашивать сохранение
                    //сохранение в .xls
                    if (saveTags.FilterIndex == 1)
                        ExcelApp.DefaultSaveFormat = Excel.XlFileFormat.xlExcel9795;
                    //сохранение в .csv
                    if (saveTags.FilterIndex == 2)
                        ExcelApp.DefaultSaveFormat = Excel.XlFileFormat.xlCSV;
                    //Установка типов данных и формат ячеек
                    excelcells = (Excel.Range)worksheet.Columns["C", Type.Missing];
                    excelcells.NumberFormat = "#####0";
                    //Cохранение файла
                    workbook.SaveAs(saveTags.FileName, ExcelApp.DefaultSaveFormat);
                    ExcelApp.Quit();
                }
                catch (Exception ex)
                {
                    //Обработка сбоя
                    ExcelApp.Quit();
                }
            }
        }
    }
}
Если на ПК установлен MS Office то этот код работает и всё хорошо сохраняет... Но! Есть такой нюанс: пробовал сохранить в Ексель-файл на компе, где Microsoft Office не установлен, либо стоит альтернативный офис типа Либры или OpenOffice... И такая конструкция уже не срабатывает!(( Выдает ошибки, что типа COM не зарегистрирован в системе и всё такое...
Отсюда у меня вопрос: как можно реализовать сохранение/открытие в/из файлов Ексель на форму программы, без вызова СОМ ну или каким-то образом, что бы привязок к Меклкософтовскому офису на ПК не было?
Заранее спасибо за помощь!
http://www.cyberforum.ru/windows-forms/thread1660359.html
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.05.2017, 09:35
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Сохранение/чтение/работа с файлами Excel без вызова СОМ (альтернативные методы) (C#):

Работа с файлами (чтение из файла)
Кто-нибудь может помочь с заданием: В исходном текстовом файле подготовить...

Сохранение Excel без запроса к пользователю
Сейчас работает выгрузка из датагрид в exel и сохранение документа с запросом к...

Работа с файлами. Пространство имён не может напрямую включать поля или методы
Задание. Разработать программу Телефонный справочник, которая позволяет...

Работа с файлами Excel
Здравствуйте! Нужен Ваш совет. Столкнулся с задачей обработки данных из...

C# и работа с Excel файлами
Доброе время суток! Меня зовут Павел, я пытаюсь освоить и в дальнейшем...

16
ViterAlex
6347 / 3551 / 1457
Регистрация: 11.02.2013
Сообщений: 7,816
Завершенные тесты: 3
11.05.2017, 09:39 #2
OpenXml. Можно начать с этого
0
Павлик Морозов
117 / 119 / 38
Регистрация: 26.10.2012
Сообщений: 402
Завершенные тесты: 1
11.05.2017, 10:19 #3
Лучший ответ Сообщение было отмечено Cha1000000 как решение

Решение

Cha1000000, можно еще проще. Уже все придумали. Бесплатная библиотека EpPlus. Неоднократно использовал ее в своих проектах. Все просто и быстро делается. Пример работы с библиотекой можно почитать здесь
1
Cha1000000
2 / 2 / 2
Регистрация: 04.06.2015
Сообщений: 204
Записей в блоге: 1
11.05.2017, 10:55  [ТС] #4
Цитата Сообщение от Павлик Морозов Посмотреть сообщение
Уже все придумали. Бесплатная библиотека EpPlus.
И этот метод решает вопрос для альтернативных офисов? Если майкросовтовский на ПК не установлен, или например вообще никакого офиса нет на ПК, а сохранить из программы файл экселевского формата нужно?
Цитата Сообщение от Павлик Морозов Посмотреть сообщение
можно еще проще.
Проще, в смысле, чем в комментарии, предложенном выше?
0
Павлик Морозов
117 / 119 / 38
Регистрация: 26.10.2012
Сообщений: 402
Завершенные тесты: 1
11.05.2017, 11:04 #5
Cha1000000, эта библиотека решает проблему чтения/сохранения если вообще ничего не установлено на ПК, кроме .Net Framework. Ей не нужны никакие сторонние либо мелкософтовские решения/компоненты. Полностью самостоятельный продукт.
0
Cha1000000
2 / 2 / 2
Регистрация: 04.06.2015
Сообщений: 204
Записей в блоге: 1
11.05.2017, 11:17  [ТС] #6
Цитата Сообщение от Павлик Морозов Посмотреть сообщение
эта библиотека решает проблему чтения/сохранения если вообще ничего не установлено на ПК, кроме .Net Framework. Ей не нужны никакие сторонние либо мелкософтовские решения/компоненты. Полностью самостоятельный продукт.
Отлично! Огромное спасибо! Буду читать, смотреть разбираться!
0
Cha1000000
2 / 2 / 2
Регистрация: 04.06.2015
Сообщений: 204
Записей в блоге: 1
12.05.2017, 13:55  [ТС] #7
Цитата Сообщение от Павлик Морозов Посмотреть сообщение
эта библиотека решает проблему...
Добрый день! Покурил вчера инфу и примеры по, предложенной вами, библиотеке, и если я правильно понял, есть один огорчающий факт - библиотека работает только с .xlsx форматом, .xls (или на пример .csv) не поддерживает. Пока изучал материалы по данной библиотеке, нашёл, что есть ещё куча разных альтернативных библиотек на подобии этой (ну каждая, видимо, со своими особенностями). А вы можете ещё какую-то конкретную порекомендовать вместо EpPlus?
0
Usaga
Эксперт .NET
3688 / 2988 / 543
Регистрация: 21.01.2016
Сообщений: 11,814
Завершенные тесты: 2
12.05.2017, 14:04 #8
Cha1000000, XLS (как и DOC) - закрытый проприетарный формат. Сложно будет по нему инфу найти или нормальную библиотеку. CSV - открытый и очень простой формат, вы его сами сможете прочесть, без сторонних библиотек.
0
Cha1000000
2 / 2 / 2
Регистрация: 04.06.2015
Сообщений: 204
Записей в блоге: 1
12.05.2017, 14:28  [ТС] #9
Цитата Сообщение от Usaga Посмотреть сообщение
Сложно будет по нему инфу найти
А как же тогда с этими форматами работают альтернативные Китайские офисы типа Libra Office, OpenOffice, WPS Office и др.?
Цитата Сообщение от Usaga Посмотреть сообщение
вы его сами сможете прочесть, без сторонних библиотек.
Если можно немного поподробнее об этом?
0
Павлик Морозов
117 / 119 / 38
Регистрация: 26.10.2012
Сообщений: 402
Завершенные тесты: 1
13.05.2017, 17:49 #10
Cha1000000, для xls другая библиотека есть. Только Вам зачем этот формат? он же древний как прах мамонта
0
Cha1000000
2 / 2 / 2
Регистрация: 04.06.2015
Сообщений: 204
Записей в блоге: 1
14.05.2017, 00:48  [ТС] #11
Цитата Сообщение от Павлик Морозов Посмотреть сообщение
для xls другая библиотека есть. Только Вам зачем этот формат? он же древний как прах мамонта
Древний формат нужен потому, что разрабатываемая программа рассчитана на широкий круг потребителей. И не известно какой пакет офиса у них может быть установлен на ПК. Некоторые "динозавры", или хардкорщики ещё пользуются как ХР так офисом 2003, а тот в свою очередь, форма xlsx не поддерживает. Да, печально и досадно, что приходится позаботиться о такой совместимости, а не взять и тупо забыть про этот реликт, и смело писать сохранение/запись под xlsx формат... Но увы, что поделать... Приходится, пока "старьё" до конца не искоренится и не канет в лету, обеспечивать поддержку совместимости и всё такое...
Про библиотеку спасибо, тоже в процессе поиска сведений на ней пока остановился, разбираюсь и ищу годные примеры как по прямому импорту/экспорту из DataGreedView в xls, так и с использованием DataTable (с которым я пока дел не имел, не пользовался и не до конца пока разобрался). Буду так же признателен, если кто поделится такими примерами. Спасибо!
0
ViterAlex
6347 / 3551 / 1457
Регистрация: 11.02.2013
Сообщений: 7,816
Завершенные тесты: 3
14.05.2017, 01:12 #12
Цитата Сообщение от Cha1000000 Посмотреть сообщение
ищу годные примеры как по прямому импорту/экспорту из DataGreedView в xls
Используй csv. Он импортируется в любой Excel.
Цитата Сообщение от Cha1000000 Посмотреть сообщение
Некоторые "динозавры", или хардкорщики ещё пользуются как ХР так офисом 2003, а тот в свою очередь, форма xlsx не поддерживает.
Неправда. Поддерживает даже для Office 2000
0
Usaga
Эксперт .NET
3688 / 2988 / 543
Регистрация: 21.01.2016
Сообщений: 11,814
Завершенные тесты: 2
14.05.2017, 06:59 #13
Цитата Сообщение от Cha1000000 Посмотреть сообщение
Если можно немного поподробнее об этом?
Сохраните что-нибудь в данном формате, потом откройте файл в блокноте и всё сразу станет ясно...
0
Cha1000000
2 / 2 / 2
Регистрация: 04.06.2015
Сообщений: 204
Записей в блоге: 1
15.05.2017, 09:35  [ТС] #14
Цитата Сообщение от ViterAlex Посмотреть сообщение
Неправда. Поддерживает даже для Office 2000
О как интересно! Не знал. Тогда можно будет подумать о том, что бы забыть об .xls и полностью перейти на xlsx... Ну и csv пожалуй буду прикручивать (на всякий случай).
0
Cha1000000
2 / 2 / 2
Регистрация: 04.06.2015
Сообщений: 204
Записей в блоге: 1
30.05.2017, 10:17  [ТС] #15
Цитата Сообщение от Павлик Морозов Посмотреть сообщение
для xls другая библиотека есть
Спасибо ещё раз за информацию про библиотеку NPOI. Из грида по примеру выгрузить в эксель данные получилось, но пока только таким макаром, напрямую:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 // create xls if not exists
            if (!File.Exists("test.xls"))
            {
                wb = HSSFWorkbook.Create(InternalWorkbook.CreateWorkbook());
 
                // create sheet
                sh = (HSSFSheet)wb.CreateSheet("Лист1");
                // 3 rows, 2 columns
                for (int i = 0; i < 3; i++)
                {
                    var r = sh.CreateRow(i);
                    for (int j = 0; j < 2; j++)
                    {
                        r.CreateCell(j);
                    }
                }
                //создаёт файл и записывает туда данные
                using (var fs = new FileStream("test.xls", FileMode.Create, FileAccess.Write))
                {
                    wb.Write(fs);
                }
А вот привязать создание файла к компоненту SaveFileDialog не могу никак, обычные текстовые файлы уже много раз через него сохранял, а тут возникла проблема. Попробую пояснить её суть. Сначала код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
private void mi_SaveToExcel_Click(object sender, EventArgs e)
        {//Сохранение в файлы Excel
            int i, j;
 
            SaveDialog.Title = "Экспорт в файл Excel";
            SaveDialog.Filter = "Файлы Mirosoft Excel 97/2000/XP/2003(*.xls) | *.xls |Файлы Mirosoft Excel(*.csv) |*.csv";
 
            if (SaveDialog.ShowDialog() == DialogResult.OK)
            {
                if (SaveDialog.OpenFile() != null)
                {
                    //File_Name = Path.GetFileName(SaveDialog.FileName); //Имя файла 
                    File_Name = SaveDialog.FileName;   //имя файла с полным путём
                    
                    if (File.Exists(File_Name))
                    {
                        workbook = HSSFWorkbook.Create(InternalWorkbook.CreateWorkbook());
                        // create sheet
                        sheet = (HSSFSheet)workbook.CreateSheet("Лист1");
                        //Создание строк таблицы
                        for (i = 0; i < ProgTable.RowCount + 1; i++)
                        {
                            if (sheet.GetRow(i) == null)
                                sheet.CreateRow(i);
 
                            //Данные таблицы                                
                            for (j = 0; j < ProgTable.ColumnCount; j++)
                            {
                                if (sheet.GetRow(i).GetCell(j) == null)
                                    sheet.GetRow(i).CreateCell(j);
 
                                if (i == 0)//Заголовок таблицы
                                {
                                    sheet.GetRow(i).GetCell(j).SetCellValue(ProgTable.Columns[j].HeaderText);
                                }
                                else
                                    if (ProgTable[j, i - 1].Value != null)
                                    {
                                        sheet.GetRow(i).GetCell(j).SetCellValue(ProgTable[j, i - 1].Value.ToString());
                                    }
                            }
                        }
                        //Cохранение файла
                        using (var fs = new FileStream(File_Name, FileMode.Open, FileAccess.Write))
                        {
                            workbook.Write(fs);
                            MessageBox.Show("Данные успешно сохранены", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
                            fs.Close();
                        }
                    }
                }
            }
}
Итак, как я заметил, отлаживая пошагово, происходит следующее, при срабатывании "SaveDialog.ShowDialog() == DialogResult.OK" файл, имя которого ввели в окне SaveDialog, создаётся сразу, и как-то похоже удерживается процессом приложения, потому как дальше
C#
1
2
3
4
using (var fs = new FileStream(File_Name, FileMode.Open, FileAccess.Write))
                        {
                            workbook.Write(fs);
                        }
ничего не делает с созданным SaveDialog, файлом, пишет что он занят...

Вот такое сообщение: "Процесс не может получить доступ к файлу "D:\Documents\base.xls", так как этот файл используется другим процессом."

Может я что-то делаю не правильно и есть какой-то более верный способ сохранить в эксель данные через SaveFileDialog? Подскажите пожалуйста, а то уже как только не пробовал, ни в какую... Пробовал SaveDialog.Dispose(); вызвать после создания файла - не помогает. Может его как-то можно "освободить"?

Добавлено через 37 минут
Коллеги! Ответ из серии: "сам спросил, сам ответил".
Я уже сам успел разобраться и найти решение. И для тех, кому интересно и может быть полезным, расскажу в чём была суть.
В общем да, SaveDialog создавал и удерживал файл, и для этого понадобилось перехватить его поток и потом закрыть его, что бы освободить файл. Создал поток:
C#
1
Stream myStream;
за тем перехватил:
C#
1
if ((myStream = SaveDialog.OpenFile()) != null)
и позже закрыл его:
C#
1
myStream.Close();
В итоге получился рабочий код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
private void mi_SaveToExcel_Click(object sender, EventArgs e)
        {//Сохранение в файлы Excel
            int i, j;
 
            SaveDialog.Title = "Экспорт в файл Excel";
            SaveDialog.Filter = "Файлы Mirosoft Excel 97/2000/XP/2003(*.xls) | *.xls |Файлы Mirosoft Excel(*.csv) |*.csv";
            Stream myStream;
            if (SaveDialog.ShowDialog() == DialogResult.OK)
            {
                if ((myStream = SaveDialog.OpenFile()) != null)
                {
                    //File_Name = Path.GetFileName(SaveDialog.FileName); //Имя файла 
                    File_Name = SaveDialog.FileName;   //имя файла с полным путём
                    myStream.Close();
                    try
                    {
                        if (File.Exists(File_Name))
                        {
                            workbook = HSSFWorkbook.Create(InternalWorkbook.CreateWorkbook());
                            // create sheet
                            sheet = (HSSFSheet)workbook.CreateSheet("Лист1");
 
                            //Создание строк таблицы
                            for (i = 0; i < ProgTable.RowCount + 1; i++)
                            {
                                if (sheet.GetRow(i) == null)
                                    sheet.CreateRow(i);
 
                                //Данные таблицы                                
                                for (j = 0; j < ProgTable.ColumnCount; j++)
                                {
                                    if (sheet.GetRow(i).GetCell(j) == null)
                                        sheet.GetRow(i).CreateCell(j);
 
                                    if (i == 0)//Заголовок таблицы
                                    {
                                        sheet.GetRow(i).GetCell(j).SetCellValue(ProgTable.Columns[j].HeaderText);
                                    }
                                    else
                                        if (ProgTable[j, i - 1].Value != null)
                                        {
                                            sheet.GetRow(i).GetCell(j).SetCellValue(ProgTable[j, i - 1].Value.ToString());
                                        }
                                }
                            }
                            //Cохранение файла
                            using (var fs = new FileStream(File_Name, FileMode.Open, FileAccess.Write))
                            {
                                workbook.Write(fs);
                                MessageBox.Show("Данные успешно сохранены", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                fs.Close();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        //Обработка сбоя
                        MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }            
        }
0
Павлик Морозов
117 / 119 / 38
Регистрация: 26.10.2012
Сообщений: 402
Завершенные тесты: 1
30.05.2017, 21:03 #16
Cha1000000, здорово что у Вас получилось самостоятельно решить проблему) Единственное, на мой взгляд, поскольку у Вас есть уже экземпляр Stream при создании файла, то в него и пишите содержимое файла. Не вижу смысла одним потоком создавать файл, другим редактировать
0
Cha1000000
2 / 2 / 2
Регистрация: 04.06.2015
Сообщений: 204
Записей в блоге: 1
31.05.2017, 15:12  [ТС] #17
Цитата Сообщение от Павлик Морозов Посмотреть сообщение
в него и пишите содержимое файла
Да, об этом я тоже думал, оставил на потом. Просто пока не рассматривал как вместо FileStream подсунуть воркбуку Stream. Вот как раз сейчас буду смотреть, а если не получится, обращусь ;-) Спасибо!

Добавлено через 3 часа 18 минут
Всё получилось! Оказывается метод .Write(...) и принимает параметр типа Stream, я просто сразу не обратил на это внимания. Вот только теперь мне интересно, а как же он тогда проглатывал переменную var fs = new FileStream(File_Name, FileMode.Open, FileAccess.Write) c типом FileStream ? Не потому ли, что она типа var и от этого может как хамелеон подгонять свой тип данных под различные "условия"?
0
31.05.2017, 15:12
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.05.2017, 15:12
Привет! Вот еще темы с решениями:

Работа с Excel файлами
Всем привет! Есть такой очень важный вопрос для меня... У меня есть файл xls,...

Чтение данных из сом по событию
Как реализовать чтение данных из порта только в том случае, если в его буфере...

Как сделать паузу без подвисания и без вызова Sleep?
Здравствуйте, как можно сделать паузу без &quot;второго&quot; потока и вешания программы...

Работа с excel без установленного Офиса
Доброго времени суток. Подскажите пожалуйста библиотеку для работы с excel (...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru