Об использовании матричных функций Excel в Visual Studio
Для использования в программе на псевдоC++ от Микрософт богатых вычислительных возможностей Excel, по идее, достаточно к своему проекту Visual C++/CLI (Windows Forms) добавить ссылку на COM-объект Microsoft Excel 14.0 Object Library (или Вашу версию Excel): меню Проект, Свойства, Список Общие свойства, вкладка COM, кнопка Добавить новую ссылку..., Обзор, выбрать COM-объект Microsoft Excel 14.0 Object Library (или ваша версия Excel вместо 14).
Кстати, нажав комбинацию клавиш Ctrl+Alt+J
, можно посмотреть, что именно мы подключили, в Обозревателе объектов.
1. Если Office установлен корректно, с обычными функциями Excel сложностей не возникнет, например, здесь мы получаем из Excel число Пи и функцию возведения в степень, считая площадь круга с радиусом R
и "отдавая" результат в текстовое поле textBox1
:
auto XL = gcnew Microsoft::Office::Interop::Excel::Application(); double R=1.; double S = XL->WorksheetFunction->Pi()*XL->WorksheetFunction->Power(R,2); //получили результат выполнения функций Excel textBox1->Text = "S = " + S; XL->Quit();
2. С матричными функциями всё немного иначе, в частности, в учебниках и инете встречается неправильный код вида:
array<double,2> ^ A = { {1, 12, 3},{-1, 1, 5},{0, 1, 1} }; array<double> ^ L = { 6, 3, 5 }; //или array<double> ^ L = gcnew array<double>(n); auto XL1 = gcnew Microsoft::Office::Interop::Excel::Application(); double det_A = XL1->Application->WorksheetFunction->MDeterm(A); textBox1->Text += "Det(A)="+Convert::ToString(det_A)+"\n"; Object ^ oA = XL1->Application->WorksheetFunction->MInverse(A); Object ^ X = XL1->Application->WorksheetFunction->MMult(oA, L); array<Object^,2> ^ Xd = (array<Object^,2> ^)X; // Чтобы ответ приобрел индексированные свойства, преобразуем его в массив textBox1->Text += String::Format ("\r\nНеизвестные равны:\r\nX1 = {0}; X2 = {1}; X3 = {2}.",Xd[1, 1], Xd[2, 1], Xd[3, 1]); // Получаем двумерный массив, индексы которого начинаются с единицы
(здесь решается СЛАУ размерности 3x3). Работать это не будет ("неверный результат выполнения функции MMult"), потому что Excel, как и Ваш учитель математики, чётко различает контексты вектор-строки и вектор-столбца, к тому же, функция MMult
(умножение матриц) хочет видеть только двумерные данные. Правильной второй строкой кода будет такая:
array<double,2> ^ L = { {6}, {3}, {5} };
Именно и только двумерная индексация матрицы из 3 строк и 1 столбца.
3. Не всегда с офисными функциями дело обстоит столь же гладко. Например, согласно доке, функция Max
(поиск максимального из чисел) имеет аж 30 (!) обязательных аргументов. И если он у вас всего один, вместо недостающих приходится писать Type::Missing
. В C# такой глупости нет, там есть опциональные параметры и значения по умолчанию для них.
Код для вычисления Excel'евской функцией максимального из 9 чисел, введённых в левые верхние ячейки компонента DataGridView
с именем dataGridView1
, будет иметь вот такой жуткий вид:
const int height=3,width=3; array<double,2> ^ A=gcnew array<double,2>(height,width); for (int i=0; i<height; i++) for (int j=0; j<width; j++) { A[i,j]=0; //а лучше "минус большое число", если не хотим специально считать не-числа как нули try { A[i,j] = System::Double::Parse(dataGridView1->Rows[i]->Cells[j]->Value->ToString()); } catch (...) {}; } auto XL1 = gcnew Microsoft::Office::Interop::Excel::Application(); double Res = XL1->Application->WorksheetFunction->Max(A, Type::Missing,Type::Missing,Type::Missing,Type::Missing,Type::Missing, Type::Missing,Type::Missing,Type::Missing,Type::Missing,Type::Missing, Type::Missing,Type::Missing,Type::Missing,Type::Missing,Type::Missing, Type::Missing,Type::Missing,Type::Missing,Type::Missing,Type::Missing, Type::Missing,Type::Missing,Type::Missing,Type::Missing,Type::Missing, Type::Missing,Type::Missing,Type::Missing,Type::Missing); String ^ Result = "Max="+Convert::ToString(Res)+"\n"; MessageBox::Show(Result,"Ответ",MessageBoxButtons::OK,MessageBoxIcon::Information); XL1->Quit();
10.04.2014, 22:59 [11812 просмотров]