Как установить значения в двумерном диапазоне Excel?
Мне нужно создать лист Excel из списка тестовых случаев в определенном формате, чтобы загрузить его на сервер. У меня есть проблемы с заполнением двухмерного диапазона "ожидаемого" и "фактического" в файле. Я использую те же методы, чтобы заполнить заголовки, которые являются одномерным массивом, и шаги (которые являются двухцветными).
Поток это:
- Защита диапазона TestCase (некоторые заголовки + шаги). Допустим, от А1 до Е14 для 1-й итерации.
- Depunding под (локальный) диапазон в пределах диапазона testCase для заголовков (например: от А1 до С1).
- Депандирование другого под (локального) диапазона в пределах диапазона testCase для заголовков (в моем случае: от D1 до E14).
- Заполните два поддиапазона значениями тестового примера (заголовки и шаги).
- Повторите, отложив следующий диапазон таблиц (от A14 до E28 в моем случае) с теми же локальными диапазонами (шаги 2-3), и заполните их, и так далее...
Исходным значением является словарь, который представляет шаги тестового примера (ключ = ожидаемый, а значение = фактический).
Вот код, который я использую:
public class TestCase
{
public Dictionary<string, string> steps;
}
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Workbooks workBooks = excelApp.Workbooks;
Workbook workbook = workBooks.Add(XlWBATemplate.xlWBATWorksheet);
Worksheet worksheet = (Worksheet)workbook.Worksheets[1];
excelApp.Visible = true;
foreach (TestCase testCase in TestCaseList.Items.GetList())
{
Range worksheetRange = GetRangeForTestCase(worksheet);
//The step above is equivalent to:
// Range worksheetRange = worksheet.get_Range("A1", "E14");
//for the first foreach iteration.
Range stepsRange = worksheetRange.get_Range("D1", "E14");
//This is a local range within the worksheetRange, not the worksheet,
//so it is always have to be between D1 to E14 for a 14th steps test case.
//Anyway, it should work at least for the 1st iteration.
//for test evaluation only. All cells between D1 to E14 are filled with "ccc"
test.Value = "ccc";
//This list of pairs which are converted to Array[,] is about to be converted to a two dimensional array
list = new List<object>();
foreach (KeyValuePair<string, string> item in testCase.Steps)
{
//Here I build the inside Array[,]
object[] tempArgs = {item.Key, item.Value};
list.Add(tempArgs);
}
object[] args = { Type.Missing, list.ToArray() };
test.GetType().InvokeMember("Value", System.Reflection.BindingFlags.SetProperty, null, test, args);
//Now, all the "ccc" within the Excel worksheet are disapeared, so the Range is correct, but the value of args[] are not set!!
}
Фактический результат выполнения этого кода состоит в том, что диапазон определен (вероятно, правильно), но его значения установлены в нуль, хотя - я могу видеть правильные значения в массиве args во время выполнения. Я также попытался установить более широкий диапазон и заполнить его range.Value = "Pake value" и увидел, что после выполнения моего кода, правильный диапазон шагов становится пустым! Итак, диапазон правильный, массив заполнен моими значениями, метод InvokeMember корректно вызывается:) Но все значения имеют значение null..
Помогите...
2 ответа
Одна ячейка или массив 1dim могут быть установлены одним из следующих способов:
Range range = SetRange();//Let's say range is set between A1 to D1
object[] args = {1, 2, 3, 4 };
//Directly
range.Value = args;
//By Reflection
range.GetType().InvokeMember("Value", System.Reflection.BindingFlags.SetProperty, null, range, args);
Массив 2dim не может быть установлен напрямую, поэтому необходимо использовать поток отражения, чтобы установить матрицу значений. Эта матрица должна быть построена перед множеством, как это:
Range range = SetRange();//Let's say range is set between A1 to C5
int rows = 5;
int columns = 3;
object[,] data = new object[rows, columns];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
//Here I build the inside Array[,]
string uniqueValue = (i + j).ToString();
data[i, j] = "Insert your string value here, e.g: " + uniqueValue;
}
}
object[] args = { data };
range.GetType().InvokeMember("Value", System.Reflection.BindingFlags.SetProperty, null, range, args);
Что касается вашей проблемы, весь диапазон установлен в нуль, я думаю, что это из-за неправильных аргументов.
Действительно, почему Type.Missing в списке аргументов?
Следовательно, это должен быть шаг в правильном направлении:
object[] args = { list.ToArray() };
test.GetType().InvokeMember("Value", System.Reflection.BindingFlags.SetProperty, null, test, args);
Более того, list.ToArray будет генерировать только массив массивов, а не матрицу, поэтому вы должны строить свою матрицу иначе, например:
object[,] data = new object[14, 2];
int row = 0;
foreach (KeyValuePair<string, string> item in testCase.Steps)
{
//Here I build the inside Array[,]
data[row, 0] = item.Key;
data[row, 1] = item.Value;
++row;
}
object[] args = { data };
И каков смысл использования InvokeMember вместо более простого:
test.Value = data;
?
Надеюсь это поможет...