Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Общие вопросы _ Excel графики в Qt

Автор: diadia_sid 16.2.2017, 16:48

Доброго времени суток.

Пишу программу для переноса данных из текстового файла в Excel. Возникла проблема с графиками. При создании нового графика создается новый лист. Как перенести график на основной лист с данными?

Код:

range = worksheet->querySubObject("Range(const QVariant&)", QVariant("A2:C200"));
range->dynamicCall("Select()");
//Создаем объект Charts (коллекция областей диаграмм)
QAxObject * charts = workbook->querySubObject("Charts");
//Добавляем новую область диаграмм
QAxObject * chart = charts->querySubObject("Add()");
//Устанавливаем имя области диаграмм
chart->dynamicCall("Name", "Name");
//Устанавливаем тип области диаграмм
chart->dynamicCall("ChartType", QVariant("xlLine"));
//Получаем доступ к текущему ряду области диаграмм
QAxObject * series = chart->querySubObject("SeriesCollection(const QVariant&)", QVariant(1));
//Устанавливаем имя ряда
series->dynamicCall("Name", "Name1");
//Получаем объект Range для оси X в виде QVariant
QVariant source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("D2:D200"));
//Устанавливаем диапазон значаний X для ряда
series->dynamicCall( "XValues", source );
//Получаем объект Range для оси Y в виде QVariant
source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("A2:A200"));
//Устанавливаем диапазон значаний Y для ряда
series->dynamicCall("Values", source);
series = chart->querySubObject("SeriesCollection(const QVariant&)", QVariant(2));
series->dynamicCall("Name", "Name2");
source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("D2:D200"));
series->dynamicCall("XValues", source);
source = worksheet->dynamicCall( "Range(const QVariant&)", QVariant("B2:B200"));
series->dynamicCall("Values", source);
series = chart->querySubObject("SeriesCollection(const QVariant&)", QVariant(3));
series->dynamicCall("Name", "Name3");
source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("D2:D200"));
series->dynamicCall("XValues", source);
source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("C2:C200"));
series->dynamicCall("Values", source);


Автор: ViGOur 16.2.2017, 17:22

Подсмотреть как это делают макросы Excel.
Я давным давно это делал так:
1. Включаешь запись макроса
2. Переносишь график на нужный тебе лист
3. Выключаешь запись макроса
4. Смотришь что там нагенерировалось в записанном макросе и переносишь это на Qt

Обычно там удобочитаемый код, который можно без проблем применить в Qt

Автор: diadia_sid 16.2.2017, 17:53

Цитата(ViGOur @ 16.2.2017, 17:22) *
Подсмотреть как это делают макросы Excel.
Я давным давно это делал так:
1. Включаешь запись макроса
2. Переносишь график на нужный тебе лист
3. Выключаешь запись макроса
4. Смотришь что там нагенерировалось в записанном макросе и переносишь это на Qt

Обычно там удобочитаемый код, который можно без проблем применить в Qt


Спасибо за участие.
Сам пользуюсь этим методом. Но вот в данном случае не получилось воплотить в рабочий код Qt =(

Автор: ViGOur 17.2.2017, 9:07

Что именно не получается?
У меня просто нет винды под рукой, чтобы посмотреть что там и как.

Автор: Алексей1153 17.2.2017, 9:09

Цитата(ViGOur)
Обычно там удобочитаемый код, который можно без проблем применить в Qt

ну уж нет, обычно код в макросе - лишь набор намёков (но уже и за это спасибо), а вот настоящий крепкий секс начинается уже при работе с QAxObject :D

Автор: Гость_diadia_sid_* 17.2.2017, 10:56

Цитата(Алексей1153 @ 17.2.2017, 9:09) *
Цитата(ViGOur)
Обычно там удобочитаемый код, который можно без проблем применить в Qt

ну уж нет, обычно код в макросе - лишь набор намёков (но уже и за это спасибо), а вот настоящий крепкий секс начинается уже при работе с QAxObject :D


Полностью согласен :lol: У меня с переносом графика секс закончился ничем :unsure:

Автор: Гость_diadia_sid_* 17.2.2017, 10:59

Цитата(ViGOur @ 17.2.2017, 9:07) *
Что именно не получается?
У меня просто нет винды под рукой, чтобы посмотреть что там и как.


Не получается перенести получившийся график (находящийся на Лист_с_графиком (при создании нового графика создается новый лист с ним (Лист_с_графиком))) на Лист_с_данными.

Автор: Алексей1153 18.2.2017, 11:04

мне эксель выдал такую подсказку , попробуй. Обрати внимание на константы - через QAxObject частенько только в виде чисел они прокатывают

Sub Макрос1()
    Range("B3:E18").Select
    Charts.Add
    
    'xlColumnClustered== 51
    ActiveChart.ChartType = xlColumnClustered
    
    ActiveChart.SetSourceData Source:=Sheets("Лист1").Range("B3:E18")
    
    'xlLocationAsObject== 2
    ActiveChart.Location Where:=xlLocationAsObject, Name:="Лист1"
End Sub

Автор: diadia_sid 22.2.2017, 12:26

Цитата(Алексей1153 @ 18.2.2017, 11:04) *
мне эксель выдал такую подсказку , попробуй. Обрати внимание на константы - через QAxObject частенько только в виде чисел они прокатывают
Sub Макрос1()
    Range("B3:E18").Select
    Charts.Add
    
    'xlColumnClustered== 51
    ActiveChart.ChartType = xlColumnClustered
    
    ActiveChart.SetSourceData Source:=Sheets("Лист1").Range("B3:E18")
    
    'xlLocationAsObject== 2
    ActiveChart.Location Where:=xlLocationAsObject, Name:="Лист1"
End Sub


Спасибо за ответ.
Сам получал такой ответ через запись макроса Excel.
И мне не удается перевезти этот код в код Qt. :(

Автор: Алексей1153 23.2.2017, 14:55

diadia_sid, вот так прокатывает

//----------------------------------------------
//Создаем объект Charts (коллекция областей диаграмм)
QAxObject * charts = workbook->querySubObject("Charts");
//Добавляем новую область диаграмм
QAxObject * chart = charts->querySubObject("Add()");

auto* range = worksheet->querySubObject("Range(const QVariant&)", QVariant("A2:C200"));
chart->dynamicCall("SetSourceData(const QVariant&)", range->asVariant());

//'xlLocationAsObject== 2
auto listname = worksheet->property("Name");
chart->dynamicCall("Location(const QVariant&,const QVariant&)",QVariant(2), listname );

//'xlColumnClustered== 51
chart->dynamicCall("ChartType(const QVariant&)", QVariant(51));
//----------------------------------------------

//Устанавливаем имя области диаграмм
chart->dynamicCall("Name", "Name");

//...



Кстати, я себе для удобства сделал обёртки QAxObject - с RAII и без аллергии на обращение по нулевому указателю - позволяет избежать многоэтажных проверок и вложенностей кода )

Автор: diadia_sid 24.2.2017, 17:16

Цитата(Алексей1153 @ 23.2.2017, 14:55) *
diadia_sid, вот так прокатывает

//----------------------------------------------
//Создаем объект Charts (коллекция областей диаграмм)
QAxObject * charts = workbook->querySubObject("Charts");
//Добавляем новую область диаграмм
QAxObject * chart = charts->querySubObject("Add()");

auto* range = worksheet->querySubObject("Range(const QVariant&)", QVariant("A2:C200"));
chart->dynamicCall("SetSourceData(const QVariant&)", range->asVariant());

//'xlLocationAsObject== 2
auto listname = worksheet->property("Name");
chart->dynamicCall("Location(const QVariant&,const QVariant&)",QVariant(2), listname );

//'xlColumnClustered== 51
chart->dynamicCall("ChartType(const QVariant&)", QVariant(51));
//----------------------------------------------

//Устанавливаем имя области диаграмм
chart->dynamicCall("Name", "Name");

//...



Кстати, я себе для удобства сделал обёртки QAxObject - с RAII и без аллергии на обращение по нулевому указателю - позволяет избежать многоэтажных проверок и вложенностей кода )


Огромное спасибо! Все получилось. Сейчас довожу до финальной версии. Немного изменил твой код (Перенес изменение Name графика и Типа графика выше (иначе не работало)):
//Создаем объект Charts (коллекция областей диаграмм)
QAxObject * charts = workbook->querySubObject("Charts");
//Добавляем новую область диаграмм
QAxObject * chart = charts->querySubObject("Add()");
auto* range = worksheet->querySubObject("Range(const QVariant&)", QVariant("A2:C200"));
chart->dynamicCall("SetSourceData(const QVariant&)", range->asVariant());

//Устанавливаем имя области диаграмм
chart->dynamicCall("Name", "Name");
//Устанавливаем тип области диаграмм
chart->dynamicCall("ChartType", QVariant("xlLine"));

//Получаем доступ к текущему ряду области диаграмм
QAxObject * series = chart->querySubObject("SeriesCollection(const QVariant&)", QVariant(1));
//Устанавливаем имя ряда
series->dynamicCall("Name", "Name1");

//Получаем объект Range для оси X в виде QVariant
QVariant source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("D2:D200"));
//Устанавливаем диапазон значений X для ряда
series->dynamicCall( "XValues", source );

//Получаем объект Range для оси Y в виде QVariant
source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("A2:A200"));
//Устанавливаем диапазон значений Y для ряда
series->dynamicCall("Values", source);
series = chart->querySubObject("SeriesCollection(const QVariant&)", QVariant(2));
series->dynamicCall("Name", "Name2");
source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("D2:D200"));
series->dynamicCall("XValues", source);
source = worksheet->dynamicCall( "Range(const QVariant&)", QVariant("B2:B200"));
series->dynamicCall("Values", source);
series = chart->querySubObject("SeriesCollection(const QVariant&)", QVariant(3));
series->dynamicCall("Name", "Name3");
source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("D2:D200"));
series->dynamicCall("XValues", source);
source = worksheet->dynamicCall("Range(const QVariant&)", QVariant("B2:B200"));
series->dynamicCall("Values", source);

//'xlLocationAsObject== 2
auto listname = worksheet->property("Name");
chart->dynamicCall("Location(const QVariant&,const QVariant&)",QVariant(2), listname );

Автор: diadia_sid 2.3.2017, 9:32

Сделал изменения размера графика. Может быть, кому-нибудь пригодится (инфы в инете совсем нет).

QAxObject * Size = worksheet->querySubObject("Shapes(const QVariant&)", "Диаграмма 1");
Size->dynamicCall("Width", "850");
Size->dynamicCall("Height", "300");

Автор: diadia_sid 2.3.2017, 11:27

Еще. Перемещение графика по листу. Значения вводятся относительно верхнего левого края листа.

QAxObject * location = worksheet->querySubObject("Shapes(const QVariant&)", "Диаграмма 1");
location ->dynamicCall("Left", "50");
location ->dynamicCall("Top", "30");

Автор: Алексей1153 3.3.2017, 7:57

diadia_sid, всё, что возвращается из querySubObject обязательно проверяй на 0, а то будут вылеты на вылете и вылетами погонять

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)