Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.88/40: Рейтинг темы: голосов - 40, средняя оценка - 4.88
0 / 0 / 1
Регистрация: 28.12.2016
Сообщений: 18
.NET 2.x

Работа с xlsx файлами

11.09.2017, 08:30. Показов 8287. Ответов 38

Студворк — интернет-сервис помощи студентам
Добрый день!
Столкнулся с довольно интересной проблемой и решил спросить тут.
Что есть на входе: папка с *.xlsx файлами и папка с одним xlsx файлом. Необходимо для каждого файла из первой папки создать лист в документе из второй папки и скопировать всё содержимое туда. С excel из c# раньше не работал, поэтому это прямо таки настоящий вызов для меня. Пожалуйста, подскажите, чего почитать, в какую сторону смотреть? На данный момент имеется такой код:
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
using System;
using System.IO;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using System.Collections.Generic;
 
namespace xlsxcopy_wf
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        #region кнопки
        private void BtnChooseFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dlg = new FolderBrowserDialog();
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                FolderTextBox.Text = dlg.SelectedPath;
            }
        }
 
        private void BtnChooseFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            if (dlg.ShowDialog() == DialogResult.OK)
                FileTextBox.Text = dlg.FileName;
        }
        #endregion
        private void BtnCopy_Click(object sender, EventArgs e)
        {
            string folder = FolderTextBox.Text;
            string[] files = Directory.GetFiles(folder, "*.xlsx");
 
            Microsoft.Office.Interop.Excel.Application excelapp = new Microsoft.Office.Interop.Excel.Application();
            foreach (var s in files)
            {
                excelapp.Visible = true;
                excelapp.Workbooks.Open(s);
                int row = 1;
                List<List<string>> maping = new List<List<string>>();
                Worksheet currentSheet = (Worksheet)excelapp.Workbooks[1].Worksheets[1];
                while (currentSheet.get_Range("A" + row).Value2 != null)
                {
                    List<string> tempList = new List<string>();
                    for (char column = 'A'; column < 'J'; column++)
                    {
                        Range cell = currentSheet.get_Range(column + row);
                        tempList.Add(cell != null ? cell.Value2.ToString() : "");
                    }
                    maping.Add(tempList);
                    row++;
                }
            }
 
        }
    }
}
То есть вроде как размапил и скопировал, а что с этим теперь делать и правильно ли делаю непонятно.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.09.2017, 08:30
Ответы с готовыми решениями:

OpenXml работа с .xlsx
Привет, как в данном коде сделать так, чтобы ячейки рисовались с автоподбором ширины столбца (чтобы все данные влезали в ширину ячейки), а...

Работа с файлами в формате .doc, .docx, .xls, .xlsx
Добрый день! Подскажите, есть ли какая-то альтернатива COM-объектам для извлечения текста из форматов .doc, .docx, .xls, .xlsx? ...

Работа с файлами xlsx
Код: import xlrd, xlwt file_obj = input('Введите путь к файлу: ') #/Users/markgurianov/Downloads/TMRCA.xlsx base_index...

38
 Аватар для Skorp24
52 / 50 / 26
Регистрация: 15.06.2009
Сообщений: 390
15.09.2017, 14:06
Студворк — интернет-сервис помощи студентам
EVG-1980, насколько я понимаю, CSV не умеет хранить стили ячеек, ширины столбцов и т. д. Потому и неприемлем во многих случаях.
0
0 / 0 / 1
Регистрация: 28.12.2016
Сообщений: 18
15.09.2017, 15:07  [ТС]
Тут ещё возник вопрос, можно ли как-то выбрать следующую пустую ячейку в столбце? Захотелось также дополнить код, чтобы на первый лист в книге-сборщике записывались названия тех книг, которые добавляю на новые листы.
0
 Аватар для Skorp24
52 / 50 / 26
Регистрация: 15.06.2009
Сообщений: 390
16.09.2017, 00:21
Anexi, как вариант, можно узнать номер последней ячейки с данными в выбранном столбце и прибавить единицу:

C#
1
int row=xlSht.Range["A1"].End[XlDirection.xlDown].Row + 1
Это для столбца А. Только нужно следить, чтобы при этом в столбце уже были данные, иначе вернёт 1 048 576.

Другой вариант:

C#
1
int row=xlSht.Cells["A:A"].SpecialCells(XlCellType.xlCellTypeLastCell).Row + 1
Работоспособность этого варианта не гарантирую, нужно проверять.
0
999 / 358 / 135
Регистрация: 27.10.2006
Сообщений: 764
16.09.2017, 15:43
ещё вариант нахождения последней заполненной ячейки в столбце А (как пример)

C#
1
int iLastRow = xlSht.Cells[xlSht.Rows.Count, "A"].End[Excel.XlDirection.xlUp].Row;  //последняя заполненная строка в столбце А
если к iLastRow прибавить +1 то получим номер пустой строки в столбце А


P.S. Он ведёт поиск заполненной ячейки снизу вверху, это лучше, чем сверху вниз
0
0 / 0 / 1
Регистрация: 28.12.2016
Сообщений: 18
18.09.2017, 08:57  [ТС]
Pavel55, Skorp24, опять то же самое, когда пытаюсь сделать так
C#
1
2
int row=xlSht.Range["A1"].End[Excel.XlDirection.xlDown].Row + 1;
xlSht.Cells[row]=xlShtName; //string xlShtName= Path.GetFileNameWithoutExtension(s);
В ячейку не забивается ничего.
Когда делаю по способу
C#
1
int iLastRow = xlSht.Cells[xlSht.Rows.Count, "A"].End[Excel.XlDirection.xlUp].Row;
VS начинает ругаться, что типу "объект" (xlSht.Cells) дают определение ".End".
0
 Аватар для Skorp24
52 / 50 / 26
Регистрация: 15.06.2009
Сообщений: 390
18.09.2017, 10:10
Цитата Сообщение от Anexi Посмотреть сообщение
Cells[row]
Впервые вижу, чтобы в таком формате указывался адрес ячеек. Попробуйте что-нибудь типа Cells["A"+row]
0
0 / 0 / 1
Регистрация: 28.12.2016
Сообщений: 18
18.09.2017, 10:16  [ТС]
Skorp24, так VS выдаёт исключение
The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG)
0
 Аватар для Skorp24
52 / 50 / 26
Регистрация: 15.06.2009
Сообщений: 390
18.09.2017, 10:37
Anexi,
C#
1
xlSht.Range["A"+row].Value=xlShtName;
Пробую так, у меня работает.

xlShtName точно ненулевой?

Добавлено через 2 минуты
И в row правду возвращает мой способ?
0
0 / 0 / 1
Регистрация: 28.12.2016
Сообщений: 18
18.09.2017, 11:00  [ТС]
Цитата Сообщение от Skorp24 Посмотреть сообщение
xlShtName точно ненулевой?
Точно, создаются листы с корректным названием.
Цитата Сообщение от Skorp24 Посмотреть сообщение
И в row правду возвращает мой способ?
вот тут всё странно, в строке
C#
1
int row = xlSht.Range["A1"].End[Excel.XlDirection.xlDown].Row + 1;
При выполнении 1го цикла значение row принимает значение 1048577, при 2м цикле row=3, при 3м row=5. В столбце заведено 2 значения в ячейке A1 и A2.
0
999 / 358 / 135
Регистрация: 27.10.2006
Сообщений: 764
18.09.2017, 11:08
Надо либо так

C#
1
xlSht.Range["A" + row].Value = xlShtName;
либо так

C#
1
xlSht.Cells[row, 1].Value = xlShtName;  //где 1 - это первый столбец, а именно столбец А

то есть смотря какой объект вы применяете - Range или Cells, от этого и нужно отталкиваться как именно писать адрес ячейки

Range["A1"].Value = "что-то"

или

Cells[номер_строки, номер_столбца].Value = "что-то"
0
 Аватар для Skorp24
52 / 50 / 26
Регистрация: 15.06.2009
Сообщений: 390
18.09.2017, 11:21
Цитата Сообщение от Anexi Посмотреть сообщение
При выполнении 1го цикла значение row принимает значение 1048577, при 2м цикле row=3, при 3м row=5. В столбце заведено 2 значения в ячейке A1 и A2.
Про 1 048 576 я уже писал выше. row=3 - поведение правильное, как я понимаю. row=5 устанавливается, если заняты 4 строки. Даже если ваша программа устанавливает в ячейки пустую строку текста, эти ячейки считаются занятыми.
0
0 / 0 / 1
Регистрация: 28.12.2016
Сообщений: 18
19.09.2017, 16:50  [ТС]
Вообще не понимаю, что делаю не так... xlShtName точно не пустой(проверкой выводится на TextBox на форме), файл Excel имеет данные в ячейке A1, и всё равно первый прогон цикла выдаёт 1048577.
Выложу код полностью, может где-то не так объявляю.
Кликните здесь для просмотра всего текста

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
64
65
66
67
68
69
70
71
using System;
using System.IO;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
 
namespace xlsxcopy_wf
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
 
            //изначальные данные с текстбоксах
            FolderTextBox.Text = @"C:\Users\user\Documents\test";
            FileTextBox.Text = @"C:\Users\user\Documents\123.xlsx";
        }
        #region кнопки
 
        //кнопка для выбора папки
        private void BtnChooseFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dlg = new FolderBrowserDialog();
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                FolderTextBox.Text = dlg.SelectedPath;
            }
        }
 
        //кнопка для выбора файла-сборщика
        private void BtnChooseFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            if (dlg.ShowDialog() == DialogResult.OK)
                FileTextBox.Text = dlg.FileName;
        }
        #endregion
        private void BtnCopy_Click(object sender, EventArgs e)
        {
            Excel.Application xlApp = new Excel.Application(); //Excel
            Excel.Workbook xlWB = xlApp.Workbooks.Open(FileTextBox.Text); //Открыть файл-сборщик
            Excel.Workbook xlWBTemp; //рабочая книга - откуда будем копировать листы
            Excel.Worksheet xlSht; //лист Excel
            Excel.Sheets xlShts;
            //xlApp.Visible = true; //отображаем Excel
            string folder = FolderTextBox.Text;
            string[] files = Directory.GetFiles(folder, "*.xlsx");
 
            foreach (var s in files)
            {                        
                xlWBTemp = xlApp.Workbooks.Open(s); //открываем файл с которого копируем лист
                string xlShtName= Path.GetFileNameWithoutExtension(s);//обрезаем путь и расширение
                xlShts = xlWBTemp.Worksheets;
                xlSht = (Excel.Worksheet)xlShts.Item[1];//выбираем лист
                xlSht.Name = xlShtName;
                xlSht.Copy(After: xlWB.Worksheets[xlWB.Worksheets.Count]); //копируем лист после всех листов справа
 
                int row = xlSht.Range["A1"].End[Excel.XlDirection.xlDown].Row + 1;
                //xlSht.Range["A"+row].Value = xlShtName; //string xlShtName= Path.GetFileNameWithoutExtension(s);
                FolderTextBox.Text = xlShtName+" -имя нового листа";
                FileTextBox.Text = row.ToString()+" -переменная row";
                xlWBTemp.Close(false); //закрываем книгу, изменения не сохраняем
                ToolStrip.Text = "Выполняется: " + s;
            }
            xlWB.Close(true);
            xlApp.Quit(); //закрываем Excel
            ToolStrip.Text = "Готово!";
            GC.Collect();
        }
    }
}
0
999 / 358 / 135
Регистрация: 27.10.2006
Сообщений: 764
19.09.2017, 17:26
Всё правильно, 1-й прогон всегда будет вам выдавать строку 1048577 так как вы используете End[Excel.XlDirection.xlDown].
Вам об этом говорили выше. Я вам дал вариант как избежать этого. Но вы всё равно решили использовать неподходящий для вас вариант.

Что такое End[Excel.XlDirection.xlDown] - это сочетание клавиш Ctrl+стрелочка вниз.
Попробуйте на пустом листе, вставить текст в ячейку А1, поставить на неё курсор и нажать Ctrl+стрелка вниз.
Куда вы переместитесь? Правильно, в ячейку А1048577. Это и делает ваш код.

Вам надо использовать вариант

int iLastRow = xlSht.Cells[xlSht.Rows.Count, "A"].End[Excel.XlDirection.xlUp].Row +1; //первая пустая ячейка в столбца А

а потом

xlSht.Range["A" + row].Value = xlShtName;


P.S. xlSht.Cells[xlSht.Rows.Count, "A"].End[Excel.XlDirection.xlUp].Row; - означает встать на ячейку А1048577 и нажать клавишу Ctrl+стрелка вверх
1
0 / 0 / 1
Регистрация: 28.12.2016
Сообщений: 18
20.09.2017, 12:45  [ТС]
Pavel55, спасибо большое за разъяснения, теперь понятно что делают эти функции Также хочу спросить, как правильно определить Excel.WorkBook.Cells[].End? У меня почему-то выдаёт ошибку на .End
Error CS1061 'object' does not contain a definition for 'End' and no extension method 'End' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
0
999 / 358 / 135
Регистрация: 27.10.2006
Сообщений: 764
20.09.2017, 14:02
Anexi, У вас в самом верху программы должна быть такая строка

using Excel = Microsoft.Office.Interop.Excel;
0
0 / 0 / 1
Регистрация: 28.12.2016
Сообщений: 18
20.09.2017, 14:51  [ТС]
Pavel55, есть такая
0
999 / 358 / 135
Регистрация: 27.10.2006
Сообщений: 764
20.09.2017, 17:56
А вы подключили COM библиотеки?

Microsoft Office XX.X Object Library (где ХХ.Х версия установленного офиса, у меня, например, 15.0)

и

Microsoft Excel XX.X Object Library (где ХХ.Х версия установленного офиса, у меня, например, 15.0)

это в меню "Проект" - "Добавить ссылку..."
0
 Аватар для СвободныйНик
191 / 180 / 114
Регистрация: 28.07.2013
Сообщений: 610
20.09.2017, 18:07
Anexi, Pavel55, должно так работать:

C#
1
2
3
4
5
//аналог нажатия комбинации клавиш [B]End + стрелка вниз[/B] от активной ячейки
//в данном случае "A10"
var iLastRow = xlSht.Range["A10"].get_End(Excel.XlDirection.xlDown).Row;
//возвращает количество заполненных ячеек в указанной колонке
var UsedRows = xlApp.WorksheetFunction.CountA(xlSht.Columns[1]);
1
0 / 0 / 1
Регистрация: 28.12.2016
Сообщений: 18
26.09.2017, 18:51  [ТС]
Всем спасибо, всё получилось Если вдруг кому-то понадобится выкладываю проект целиком. Теперь буду пробовать сделать подобное в OpenXML, благо документации много ) Ещё раз всем спасибо за помощь!
Вложения
Тип файла: 7z xlsxcopy_wf.7z (826.8 Кб, 4 просмотров)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.09.2017, 18:51
Помогаю со студенческими работами здесь

Как работать с файлами doc, docx,xlsx
Видел библиотеку ActiveQt, ну там про DOC я даже не понимаю как с ним раьотать, есть мейби пример, кучу времени облегчит ну или есть у...

Xls и Xlsx библиотеки и компоненты для работы с файлами
Кто может посоветовать библиотеку или компоненты для работы с файлами (Xls и Xlsx). Желательно чтобы работать можно было без установки...

Есть ли какой-нибудь модуль для работы с XLSX файлами?
Спасибо большое, за развернутый ответ, теперь буду более детально учить Python. Подскажите пожалуйста, а есть ли какая нибудь библиотека,...

Работа с xlsx
Здравствуйте ув. форумчане. Сразу перейду к делу: Есть форма, в которой я рассчитываю те или иные формулы, которые впоследствии...

Быстрая работа с xlsx
Подскажите, плиз, какой способ работы с xlsx-файлами будет наиболее быстрым? Интересует поиск, удаление, замена (запись). По поводу...


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

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru