Use QAxObject to save the data of QTableView as local excel sheets - c++

I need a feature to save the data of qtableview as local excel sheet,i can get data from qtableview,i can make sure that values have been token correctly from qtableview when i step into my 'SetCellValue' function,but they are incorrect in my excel sheet
Get value from qtableview and set them into my excel sheet
for (int row = 0; row < m_nDefectNum[2]; row++)
{
QModelIndex NoModelIndex = categoriesTableList[2]->model()->index(row, 0);
QModelIndex NameModelIndex = categoriesTableList[2]->model()->index(row, 1);
QModelIndex backACountModelIndex = categoriesTableList[2]->model()->index(row, 2);
QModelIndex backARateModelIndex = categoriesTableList[2]->model()->index(row, 3);
QModelIndex backBCountModelIndex = categoriesTableList[3]->model()->index(row, 2);
QModelIndex backBRateModelIndex = categoriesTableList[3]->model()->index(row, 3);
QString backCountStr = QString::number(categoriesTableList[2]->model()->data(backACountModelIndex).toInt() + categoriesTableList[3]->model()->data(backBCountModelIndex).toInt());
QString backRateStr = QString::number(categoriesTableList[2]->model()->data(backARateModelIndex).toDouble() + categoriesTableList[3]->model()->data(backBRateModelIndex).toDouble(), 'f', 2) + "%";
excel->SetCellValue(row + 1, 0, categoriesTableList[2]->model()->data(NoModelIndex).toString());
excel->SetCellValue(row + 1, 1, categoriesTableList[2]->model()->data(NameModelIndex).toString());
excel->SetCellValue(row + 1, 2, backCountStr);
excel->SetCellValue(row + 1, 3, backRateStr);
}
SetCellValue
void ExcelExporterHelper::SetCellValue(int row, int column, const QString& value)
{
int cellRow = row + 1;
int cellCol = column + 1;
QAxObject* pRange = m_pSheet->querySubObject("Cells(int,int)", cellRow, cellCol);
pRange->dynamicCall("SetValue(const QString&)",value);
}
such as , the value i get are "300 30%",they will become "300 300%" when i see the excel file,i don't know what's wrong with my code, i need some help,
i can sure that values have been token from qtableview successfully,but failed when they are saved into excel
step into
my excel

Related

Qcombobox remove and add item in C++ Qt

Creating a combobox in Qtableview2 column 1 and passing values from Qtableview1 column1
so i am storing column1 table1 values in Qstringlist and passing to combobox
void cymodel::rowvalues() {
QAbstractItemModel* table1 = ui.tableView->model();
QAbstractItemModel* table2 = ui.tableView_2->model();
QStringList colvallist1;
for (int r = 0, maxI = table1->rowCount(); r < maxI; ++r)
colvallist1.append(table1->data(table1->index(r, 0)).toString());//store value in stringlist
for (int i = 0, maxI = table2->rowCount(); i < maxI; ++i)//for all rows
{
const QModelIndex idx = table2->index(i, 1);
QComboBox* combo = qobject_cast<QComboBox*>(ui.tableView_2->indexWidget(idx));
if (!combo)
{
combo = new QComboBox(); // make combo
ui.tableView_2->setIndexWidget(idx, combo);// add combo
}
// combo->model()->removeRows(0, combo->count(), combo->rootModelIndex());
colvallist1.removeDuplicates(); // clear duplicates in colvallist1
colvallist1.removeAll(QString("")); //remove empty row data
combo->setPlaceholderText(QString(" "));
combo->addItems(colvallist1);
}
}
connect(ui.tableView->model(), &QAbstractItemModel::dataChanged, this,
&cymodel::rowvalues);
Using removerows() all items are removed everytime,,if I added some values in column0 table1 then select in combobox and again adding values in table1 Column0 that time combobox selection go away
but if i don't use removerows() then when I'm adding new item to combobox then its adding multiple time like 2 values added then i add 2 more in table1 col then in combobox it become 4
So, how to add those that appear in colvallist1 but are not already in the combo & remove those that don't appear in colvallist1 ??
Thanks Plz help!!
thnks,,,i solved this..
to remove the items in combobox which are not in colvallist1..without change in selection
here is the code--
void cymodel::rowvalues() {
QAbstractItemModel* table1 = ui.tableView->model();
QAbstractItemModel* table2 = ui.tableView_2->model();
QStringList colvallist1;
for (int r = 0, maxI = table1->rowCount(); r < maxI; ++r)
colvallist1.append(table1->data(table1->index(r, 0)).toString());//store value in stringlist
for (int i = 0, maxI = table2->rowCount(); i < maxI; ++i)//for all rows
{
const QModelIndex idx = table2->index(i, 1);
QComboBox* combo1 = qobject_cast<QComboBox*>(ui.tableView_2-
>indexWidget(idx));
if (!combo1)
{
combo1 = new QComboBox(); // make combo
ui.tableView_2->setIndexWidget(idx, combo);// add combo
}
colvallist1.removeDuplicates(); // clear duplicates in colvallist1
colvallist1.removeAll(QString("")); //remove empty row data
combo1->setPlaceholderText(QString(" "))
QString selected = combo1->currentText();
int indx = combo1->currentIndex();
combo1->clear();
combo1->addItems(colvallist1);
combo1->findData(selected);
combo1->setCurrentIndex(indx);
combo1->setCurrentText(selected);
}

QT QTableWidget::item() returns nullptr even when widget assigned to it

This is driving me nuts. Here's the relevant code:
//Inside UI class
QTableWidget *table_view;
Later,
QLabel* lb_param_id = new QLabel(this);
lb_param_id->setText(QString::number(param_id));
QLabel* lb_param_name = new QLabel(this);
lb_param_name->setText(QString(param_name));
QLineEdit* te_value = new QLineEdit(this);
te_value->setText(QString(value));
QPushButton* pb_command = new QPushButton();
pb_command->setText("Change");
...
if(ui->table_view->rowCount() <= param_id)
ui->table_view->setRowCount(param_id + 1);
ui->table_view->setCellWidget(param_id, 0, lb_param_id);
ui->table_view->setCellWidget(param_id, 1, lb_param_name);
ui->table_view->setCellWidget(param_id, 2, te_value);
ui->table_view->setCellWidget(param_id, 3, pb_command);
for(int i =0; i < ui->table_view->rowCount(); ++i)
{
for(int j = 0; j < ui->table_view->columnCount(); ++j)
{
QTableWidgetItem* item = ui->table_view->item(i, j);
//Here, item is nullptr. Why?
item->setForeground(QColor::fromRgb(255,255,255));
}
}
I set widgets, then try to change foreground of all widgets inside QTableWidget. However, what is returned from ui->table_view->item() is nullptr. What is going on here? btw, The column count is set at initialization.
Add following few lines of code.
if(ui->table_view->rowCount() <= param_id)
ui->table_view->setRowCount(param_id + 1);
ui->table_view->setColumnCount(4);
ui->table_view->setItem(param_id, 0, new QTableWidgetItem());
ui->table_view->setItem(param_id, 1, new QTableWidgetItem());
ui->table_view->setItem(param_id, 2, new QTableWidgetItem());
ui->table_view->setItem(param_id, 3, new QTableWidgetItem());
ui->table_view->setCellWidget(param_id, 0, lb_param_id);
...
Basically, you need to insert the data into the cell first before you can set widget. In your case, you don't have meaning fully data.
Inspecting the qt source, this is the how setCellWidget() imaplemented:
void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
{
QModelIndex index = model()->index(row, column, QModelIndex());
QAbstractItemView::setIndexWidget(index, widget);
}
Without setting the cell first, the model index is invalid index. I agree qt should insert the data if returned index is invalid. For now, you have to work with qt code.

QTableView resize vertically data not refreshed

I've implemented a table through deriving QTableView and QAbstractTableModel. It all seems to work fine except when I resize the table vertically the rows that were originally out of view don't show any data.
There is no issue when resizing horizontally possibly because I've overridden the resizeEvent() method and am recalculating column widths which I obviously don't do if the table is resized vertically.
I'm using the following code in the model to add data to the table:
bool DDUTableModel::insertRow(int row, const QModelIndex& parent)
{
beginInsertRows(parent, row, row);
digital_display_list_.append(DigitalDisplayData(path_));
endInsertRows();
return true;
}
The resizeEvent() looks like this:
void DDUTableView::resizeEvent(QResizeEvent* ev)
{
int num_columns = NUM_ELEMENTS(COLUMN_WIDTHS);
if (num_columns > 0) {
int width = ev->size().width();
int used_width = 0;
// Set our widths to be a percentage of the available width
for (int i = 0; i < num_columns - 1; i++) {
int column_width = (width * COLUMN_WIDTHS[i]) / 100;
this->setColumnWidth(i, column_width);
used_width += column_width;
}
// Set our last column to the remaining width
this->setColumnWidth(num_columns - 1, width - used_width);
}
}
Any ideas?
The problem was with the resizeEvent(). I need to also invoke the method in the QTableView class that I derived from to force a refresh on vertical resizing. Amended method looks like this:
void DDUTableView::resizeEvent(QResizeEvent* ev)
{
int num_columns = NUM_ELEMENTS(COLUMN_WIDTHS);
if (num_columns > 0) {
int width = ev->size().width();
int used_width = 0;
// Set our widths to be a percentage of the available width
for (int i = 0; i < num_columns - 1; i++) {
int column_width = (width * COLUMN_WIDTHS[i]) / 100;
this->setColumnWidth(i, column_width);
used_width += column_width;
}
// Set our last column to the remaining width
this->setColumnWidth(num_columns - 1, width - used_width);
}
QTableView::resizeEvent(ev);
}

QTableView slow performance with 1000s of visible cells

I'm using QTableView in Qt 4.8.4 to visualize a lot of data (large/many protein amino acid sequences) and I'd like to be able to make cells as small as possible so I can pack as many as possible into a given window. The problem I'm running into is that when there are many cells displayed at once, everything (e.g. scrolling, resizing, and in general repainting) slows down to a crawl. Here's some sample code (adapted from the examples/tutorials/1_readonly tutorial):
MyModel::MyModel(QObject *parent):QAbstractTableModel(parent){}
int MyModel::rowCount(const QModelIndex & /*parent*/) const {
return 200;
}
int MyModel::columnCount(const QModelIndex & /*parent*/) const {
return 60;
}
QVariant MyModel::data(const QModelIndex &index, int role) const {
if (role == Qt::DisplayRole){
return QString("%1").arg(index.row()%10);
}
return QVariant();
}
and here's the code which runs the table view:
int main(int argc, char *argv[]){
QApplication a(argc, argv);
QTableView tableView;
tableView.horizontalHeader()->setDefaultSectionSize(15);
tableView.verticalHeader()->setDefaultSectionSize(15);
tableView.setFont(QFont("Courier",12));
MyModel myModel(0);
tableView.setModel( &myModel );
tableView.setGeometry(0,0,1000,1000);
tableView.show();
return a.exec();
}
When I use Instruments on OSX while scrolling up and down, it's spending a lot of time in QWidgetPrivate::drawWidget and down the stack, QWidgetPrivate::paintSiblingsRecursive... i.e., it's spending a lot of time redrawing my table.
I'm new to Qt, so I'm not sure how to approach this problem. Should I:
override the paint method? i.e. perhaps I could save my whole table as an image, and when scrolling happens, to just repaint the image until movement stops (and then return to painting the table directly)?
Not use tables in Qt at all? Perhaps I can just use a Text field to accomplish my purposes? e.g. for each letter in the text, i'd like hovertext, selections, coloring letter's backgrounds, etc.
Both of these options seem like a lot of work to make up for ground lost by switching away from QTableView. Are there any other suggestions?
QTableView is known to be slow when dealing with large datasets. I suggest you to switch to Qt Graphics View Framework. It's much more efficient and is flexible enough to display a table.
QGraphicsScene scene;
QFont font("Courier",12);
QFontMetrics font_metrics(font);
int padding = 2;
int column_width = font_metrics.width("X") + padding * 2;
int row_height = font_metrics.height() + padding * 2;
int rows = 200, columns = 60;
for(int x = 0; x < columns; x++) {
for(int y = 0; y < rows; y++) {
QGraphicsSimpleTextItem* item = scene.addSimpleText(QString().setNum(y % 10), font);
item->setPos(x * column_width + padding, y * row_height + padding);
}
}
for(int x = 0; x < columns + 1; x++) {
int line_x = x * column_width;
scene.addLine(line_x, 0, line_x, rows * row_height)->setPen(QPen(Qt::gray));
}
for(int y = 0; y < rows + 1; y++) {
int line_y = y * row_height;
scene.addLine(0, line_y, columns * column_width, line_y)->setPen(QPen(Qt::gray));
}
QGraphicsView view(&scene);
view.resize(700, 700);
view.show();
Try to use QTreeView, but set uniformRowHeights to true. Millions of items worked last time I've checked.
EDIT: QTreeView supports tables and more!
i'm using a 1e8 rows table and had to switch to QTreeView with setUniformRowHeights(true);

How to select next row in QTableView programmatically

I have QTableView subclass that I am marking and saving its state with this :
connect(this,
SIGNAL(clicked(const QModelIndex &)),
this,
SLOT(clickedRowHandler(const QModelIndex &))
);
void PlayListPlayerView::clickedRowHandler(const QModelIndex & index)
{
int iSelectedRow = index.row();
QString link = index.model()->index(index.row(),0, index.parent()).data(Qt::UserRole).toString();
emit UpdateApp(1,link );
}
now i like programmatically to move the selection to the next row (not by pressing the row with the mouse)
and invoking clickedRowHandler(...) how shall i do that ?
Thanks
You already have the current row index, so use something like the following to get the modelindex for the next row
QModelIndex next_index = table->model()->index(row + 1, 0);
Then you can set that modelindex as the current one using
table->setCurrentIndex(next_index);
Obviously you'll need to make sure you're not running past the end of the table, and there's probably some extra steps to make sure the entire row is selected, but that should get you closer.
/*
* selectNextRow() requires a row based selection model.
* selectionMode = SingleSelection
* selectionBehavior = SelectRows
*/
void MainWindow::selectNextRow( QTableView *view )
{
QItemSelectionModel *selectionModel = view->selectionModel();
int row = -1;
if ( selectionModel->hasSelection() )
row = selectionModel->selection().first().indexes().first().row();
int rowcount = view->model()->rowCount();
row = (row + 1 ) % rowcount;
QModelIndex newIndex = view->model()->index(row, 0);
selectionModel->select( newIndex, QItemSelectionModel::ClearAndSelect );
}