#c# #loops #visual-studio-2017 #epplus
#c# #циклы #visual-studio-2017 #epplus
Вопрос:
Итак, я играюсь с EPPlus и C #, и у меня есть форма с некоторыми текстовыми полями, и я пытаюсь добавить значения текстовых полей в следующую доступную пустую строку, и у меня возникают некоторые проблемы. Я пробовал несколько разных способов найти следующую доступную пустую строку, чтобы добавить значения текстового поля к этой строке, всегда пропуская первую строку, поскольку в ней есть заголовки моих столбцов.
Ближе всего я подошел к тому, чтобы заставить его постоянно записывать в строки 2 и 3, но он всегда записывал бы одну и ту же информацию.
//create an instance of the first sheet in the loaded file
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets["Sheet1"];
var r = worksheet.Dimension.End.Row;
for (int i = 1; i <= r; i )
{
worksheet.Cells[i, 1].Value = comboBox1.Text;
worksheet.Cells[i, 2].Value = textBox1.Text;
worksheet.Cells[i, 3].Value = textBox2.Text;
worksheet.Cells[i, 4].Value = textBox3.Text;
worksheet.Cells[i, 5].Value = textBox4.Text;
worksheet.Cells[i, 6].Value = richTextBox1.Text;
}
Вот весь мой код на случай, если вам нужно увидеть, как или с чем я работаю.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OfficeOpenXml;
using System.IO;
using OfficeOpenXml.Style;
namespace NetworkManager
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void Form1_Load(object sender, EventArgs e)
{
StreamReader sr = new StreamReader(@".Owners.txt");
string x = sr.ReadToEnd();
string[] y = x.Split('n');
foreach (string s in y)
{
comboBox1.Items.Add(s);
}
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
// Create a new blank package/file
using (var package = new ExcelPackage())
{
// Add a new worksheet to the empty workbook
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Sheet1");
// Set the header text
worksheet.HeaderFooter.OddHeader.CenteredText = "amp;24amp;Uamp;"Arial,Regular Bold" Router IP" textBox5;
//Set column width
worksheet.Column(1).Width = 20;
worksheet.Column(2).Width = 25;
worksheet.Column(3).Width = 20;
worksheet.Column(4).Width = 25;
worksheet.Column(5).Width = 25;
worksheet.Column(6).Width = 25;
// Border and Font for Column Headers
worksheet.Cells["A1:F1"].Style.Border.BorderAround(ExcelBorderStyle.Thick); // Thick border around Column Headers
worksheet.Cells["A1:F1"].Style.Font.Bold = true; // Bold text for Column Headers
worksheet.Cells["A1:F1"].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
//Add column headers
worksheet.Cells[1, 1].Value = "Owner";
worksheet.Cells[1, 2].Value = "Device Name";
worksheet.Cells[1, 3].Value = "Ip Address";
worksheet.Cells[1, 4].Value = "Mac Address 1";
worksheet.Cells[1, 5].Value = "Mac Address 2";
worksheet.Cells[1, 6].Value = "Notes";
// set some document properties
package.Workbook.Properties.Title = "NetworkManager";
package.Workbook.Properties.Author = "David Goodwin";
package.Workbook.Properties.Comments = "This is a program to help manager your network addresses";
//Save your file
FileInfo fi = new FileInfo(@".ExportedDocNetworkManager.xlsx");
package.SaveAs(fi);
MessageBox.Show("New File Created!");
}
}
private void loadToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
private void button1_Click(object sender, EventArgs e) // Append data to already existing excel document
{
//the path of the file
string filePath = ".\ExportedDoc\NetworkManager.xlsx";
//create a fileinfo object of an excel file on the disk
FileInfo file = new FileInfo(filePath);
//create a new Excel package from the file
using (ExcelPackage excelPackage = new ExcelPackage(file))
{
//create an instance of the first sheet in the loaded file
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets["Sheet1"];
var r = worksheet.Dimension.End.Row;
for (int i = 1; i <= r; i )
{
worksheet.Cells[i, 1].Value = comboBox1.Text;
worksheet.Cells[i, 2].Value = textBox1.Text;
worksheet.Cells[i, 3].Value = textBox2.Text;
worksheet.Cells[i, 4].Value = textBox3.Text;
worksheet.Cells[i, 5].Value = textBox4.Text;
worksheet.Cells[i, 6].Value = richTextBox1.Text;
}
/*
// check to find last empty row to add new rows.
int rowCount = worksheet.Dimension.End.Row;
int colCount = worksheet.Dimension.End.Column;
for (int row = 1; row <= rowCount; row )
{
// Create a bool
bool RowIsEmpty = true;
for (int col = 1; col <= colCount; col )
{
// check if the cell is empty or not
if (worksheet.Cells[row, col].Value != null)
{
RowIsEmpty = false;
}
}
// if row is empty, hit flag and write data
if (RowIsEmpty == true)
{
MessageBox.Show("Test");
// write data to next available row
int i = 1;
foreach (var item in worksheet.Cells)
{
worksheet.Cells[1, i].Value = comboBox1.Text;
worksheet.Cells[2, i].Value = textBox1.Text;
worksheet.Cells[3, i].Value = textBox2.Text;
worksheet.Cells[4, i].Value = textBox3.Text;
worksheet.Cells[5, i].Value = textBox4.Text;
worksheet.Cells[6, i].Value = richTextBox1.Text;
i ;
}
}
}
*/
/*
// add some data
worksheet.Cells["A2"].Value = comboBox1.Text;
worksheet.Cells["B2"].Value = textBox1.Text;
worksheet.Cells["C2"].Value = textBox2.Text;
worksheet.Cells["D2"].Value = textBox3.Text;
worksheet.Cells["E2"].Value = textBox4.Text;
worksheet.Cells["F2"].Value = richTextBox1.Text;
*/
// after adding the items, clear the fields
textBox1.Clear();
textBox2.Clear();
textBox3.Clear();
textBox4.Clear();
textBox5.Clear();
richTextBox1.Clear();
//save the changes
excelPackage.Save();
}
}
}
}
Похоже, это работает, но я не уверен, что это так эффективно, как могло бы быть. Я также тестировал, вручную удаляя строку в середине, и она по-прежнему идет в конец столбца, что хорошо, я могу рассмотреть возможность удаления пустых строк между строкой 1 и rowCount .
//Cells only contains references to cells with actual data
int rowCount = worksheet.Dimension.End.Row;
int colCount = worksheet.Dimension.End.Column;
var cells = worksheet.Cells;
var rowIndicies = cells
.Select(c => c.Start.Row)
.Distinct()
.ToList();
//Skip the header row
for (var i = 1; i <= rowCount; i )
{
// add some data
worksheet.Cells[rowCount 1, 1].Value = comboBox1.Text;
worksheet.Cells[rowCount 1, 2].Value = textBox1.Text;
worksheet.Cells[rowCount 1, 3].Value = textBox2.Text;
worksheet.Cells[rowCount 1, 4].Value = textBox3.Text;
worksheet.Cells[rowCount 1, 5].Value = textBox4.Text;
worksheet.Cells[rowCount 1, 6].Value = richTextBox1.Text;
}
Комментарии:
1. Я бы создал отдельную функцию, которая берет лист или диапазон и возвращает первую пустую строку. Это будет проще тестировать изолированно.
2. Итак, я думаю, у меня получилось, но мне интересно, лучший ли это способ сделать это или нет.
3. Вы могли бы обновить вопрос своим новым кодом.
4. Спасибо, 😀 это то, что я пытался сделать 🙂
5. Выделение ее в отдельную функцию также было бы неплохой идеей, потому что я просто думал о возможности поиска в ячейках определенного IP-адреса, а затем о возможности удаления строки, если она найдена.
Ответ №1:
Если все, что вы пытаетесь сделать, это перейти в самый низ вашего листа и добавить одну строку со значениями из элементов управления формы, вам вообще не должен понадобиться for
цикл. Что-то вроде этого должно это сделать:
//Cells only contains references to cells with actual data
int rowCount = worksheet.Dimension.End.Row;
int colCount = worksheet.Dimension.End.Column;
var cells = worksheet.Cells;
var maxRow = cells
.Select(c => c.Start.Row)
.Max();
//Go to the next row after the max
maxRow ;
worksheet.Cells[maxRow, 1].Value = comboBox1.Text;
worksheet.Cells[maxRow, 2].Value = textBox1.Text;
worksheet.Cells[maxRow, 3].Value = textBox2.Text;
worksheet.Cells[maxRow, 4].Value = textBox3.Text;
worksheet.Cells[maxRow, 5].Value = textBox4.Text;
worksheet.Cells[maxRow, 6].Value = richTextBox1.Text;
Дайте мне знать, если я неправильно понимаю.