Read/write 个值来自 Excel 个数据源文件
Read/write values from Excel data source file
从,我了解到我们无法更新到正在读取的 CSV 数据源文件,但我们可以随时更新到 Excel数据源?
[TestMethod]
[DataSource("System.Data.Odbc", "Dsn=Excel Files;Driver={Microsoft Excel Driver (*.xls)};dbq=|DataDirectory|\data.xlsx;defaultdir=.;driverid=790;maxbuffersize=2048;pagetimeout=5;readonly=false;", "Sheet1$", DataAccessMethod.Random)]
public void ExcelReadWrite()
{
String a = TestContext.DataRow["Scenario"].ToString();
String b = "New Order # generated from the app";
Console.WriteLine(a + ": " + b);
TestContext.DataRow["Order#"] = b; //Is this possible? if yes, how to write it back?
}
如果这行不通,我应该采取什么方法?
也许 Microsoft.Office.Interop.Excel;
或 DataTable
?走这些路,我们还能用[DataSource]
吗?
更新:
写入新文件并不能很好地工作。原因是:
每个数据源行将在一次迭代中处理。数据源文件将始终是相同的原始副本。因此,每次迭代只能更新一行,并且会丢失之前更新的值。
如果每次迭代都覆盖新文件,最终只有一行包含更新的值;如果你每次迭代都创建不同的文件,你最终会得到太多的新文件,一个文件只包含一行更新的值,其余的都是一样的。例如,如果您的数据源文件包含 5000 行,您将创建 5000 个新文件。
读取数据源然后用更新后的数据写回将不起作用,因为测试[TestMethod]
的每次迭代都是使用原始 数据源执行的。上一次迭代的更新数据将在每次迭代中被覆盖。您最终只得到最后一次迭代的一行更新数据。
解决方法:
data.xlsx:
Scenario SecondCol Result
89 23 Value
11 800 Value
888 111 Value
- 将数据源中的数据加载到 Excel.Workbook 对象中
- 更新 Excel.Workbook
的数据
- 用更新后的 Excel.Workbook 对象覆盖数据源文件
下面是一个例子。 data.xlsx
是 Excel 数据源文件。
[TestMethod]
[DataSource("System.Data.Odbc", "Dsn=Excel Files;Driver={Microsoft Excel Driver (*.xls)};dbq=|DataDirectory|\data.xlsx;defaultdir=.;driverid=790;maxbuffersize=2048;pagetimeout=5;readonly=false", "Sheet1$", DataAccessMethod.Sequential)] // This is working Excel.xlsx connection!!! Excel (ODBC, Dsn)
public void ExcelReadWrite()
{
//Open copied Excel file and create Excel object
string projectName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
//string dir = Environment.CurrentDirectory + @"\..\..\..\";
string dir = System.IO.Directory.GetParent(Environment.CurrentDirectory).Parent.Parent.FullName;
string targetFilename = "data.xlsx";
string targetFile = dir + projectName + @"\" + targetFilename;
object missing = Type.Missing;
object misValue = System.Reflection.Missing.Value;
Excel.Application excel = new Excel.Application();
Excel.Workbook wb = excel.Workbooks.Open(targetFile, true, false);
Excel.Worksheet ws = wb.Sheets[1];
Excel.Range wr = ws.UsedRange;
int rowCount = wr.Rows.Count;
int colCount = wr.Columns.Count;
//make some example data update for current iteration
int row = TestContext.DataRow.Table.Rows.IndexOf(TestContext.DataRow); //current iteration data row. zero base
int generatedData = Convert.ToInt32(TestContext.DataRow[0]) + Convert.ToInt32(TestContext.DataRow[1]); //read from DataSource
ws.Cells[row + 2, 3] = generatedData; //Worksheet, not zero base, and header row counts
// ======================================================
excel.DisplayAlerts = false;
wb.SaveAs(targetFile, Excel.XlFileFormat.xlWorkbookDefault, misValue,
misValue, misValue, misValue,
Excel.XlSaveAsAccessMode.xlExclusive, misValue,
misValue, misValue, misValue, misValue);
wb.Close(missing, missing, missing);
excel.Quit();
}
更新:
没有必要制作数据源文件的新副本。如果设置 readonly=false
,则可以使用 Excel.Workbook.SaveAs
命令更新数据源文件。请注意 [DataSource]
部分中的此设置。
从
[TestMethod]
[DataSource("System.Data.Odbc", "Dsn=Excel Files;Driver={Microsoft Excel Driver (*.xls)};dbq=|DataDirectory|\data.xlsx;defaultdir=.;driverid=790;maxbuffersize=2048;pagetimeout=5;readonly=false;", "Sheet1$", DataAccessMethod.Random)]
public void ExcelReadWrite()
{
String a = TestContext.DataRow["Scenario"].ToString();
String b = "New Order # generated from the app";
Console.WriteLine(a + ": " + b);
TestContext.DataRow["Order#"] = b; //Is this possible? if yes, how to write it back?
}
如果这行不通,我应该采取什么方法?
也许 Microsoft.Office.Interop.Excel;
或 DataTable
?走这些路,我们还能用[DataSource]
吗?
更新: 写入新文件并不能很好地工作。原因是:
每个数据源行将在一次迭代中处理。数据源文件将始终是相同的原始副本。因此,每次迭代只能更新一行,并且会丢失之前更新的值。
如果每次迭代都覆盖新文件,最终只有一行包含更新的值;如果你每次迭代都创建不同的文件,你最终会得到太多的新文件,一个文件只包含一行更新的值,其余的都是一样的。例如,如果您的数据源文件包含 5000 行,您将创建 5000 个新文件。
读取数据源然后用更新后的数据写回将不起作用,因为测试[TestMethod]
的每次迭代都是使用原始 数据源执行的。上一次迭代的更新数据将在每次迭代中被覆盖。您最终只得到最后一次迭代的一行更新数据。
解决方法:
data.xlsx:
Scenario SecondCol Result
89 23 Value
11 800 Value
888 111 Value
- 将数据源中的数据加载到 Excel.Workbook 对象中
- 更新 Excel.Workbook 的数据
- 用更新后的 Excel.Workbook 对象覆盖数据源文件
下面是一个例子。 data.xlsx
是 Excel 数据源文件。
[TestMethod]
[DataSource("System.Data.Odbc", "Dsn=Excel Files;Driver={Microsoft Excel Driver (*.xls)};dbq=|DataDirectory|\data.xlsx;defaultdir=.;driverid=790;maxbuffersize=2048;pagetimeout=5;readonly=false", "Sheet1$", DataAccessMethod.Sequential)] // This is working Excel.xlsx connection!!! Excel (ODBC, Dsn)
public void ExcelReadWrite()
{
//Open copied Excel file and create Excel object
string projectName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
//string dir = Environment.CurrentDirectory + @"\..\..\..\";
string dir = System.IO.Directory.GetParent(Environment.CurrentDirectory).Parent.Parent.FullName;
string targetFilename = "data.xlsx";
string targetFile = dir + projectName + @"\" + targetFilename;
object missing = Type.Missing;
object misValue = System.Reflection.Missing.Value;
Excel.Application excel = new Excel.Application();
Excel.Workbook wb = excel.Workbooks.Open(targetFile, true, false);
Excel.Worksheet ws = wb.Sheets[1];
Excel.Range wr = ws.UsedRange;
int rowCount = wr.Rows.Count;
int colCount = wr.Columns.Count;
//make some example data update for current iteration
int row = TestContext.DataRow.Table.Rows.IndexOf(TestContext.DataRow); //current iteration data row. zero base
int generatedData = Convert.ToInt32(TestContext.DataRow[0]) + Convert.ToInt32(TestContext.DataRow[1]); //read from DataSource
ws.Cells[row + 2, 3] = generatedData; //Worksheet, not zero base, and header row counts
// ======================================================
excel.DisplayAlerts = false;
wb.SaveAs(targetFile, Excel.XlFileFormat.xlWorkbookDefault, misValue,
misValue, misValue, misValue,
Excel.XlSaveAsAccessMode.xlExclusive, misValue,
misValue, misValue, misValue, misValue);
wb.Close(missing, missing, missing);
excel.Quit();
}
更新:
没有必要制作数据源文件的新副本。如果设置 readonly=false
,则可以使用 Excel.Workbook.SaveAs
命令更新数据源文件。请注意 [DataSource]
部分中的此设置。