Постепенное замедление записи в Excel из QList
Программа выполняет выгрузку данных из одного Excel в массив строк QList (1-ый Excel закрывается). Затем последовательно двигаясь по второму файлу Excel,производит запись во второй Excel, при условии совпадения двух 2-х пар значений между сравниваемой ячейкой в Excel и одним из элементов массива QList.Проблема в том что происходит последовательное замедление выполнения программы. Вначале быстро стартует затем скорость постепенно падает. Отмерял количество записей в Excel каждые 5 секунд. Средний результат:
Делал два снимка памяти при отладке, до и после выполнения цикла на предмет утечки памяти. Не обнаружил. Может кто чего подскажет. Заранее благодарю. Соответственно прикладываю основную функцию программы, которая отвечает за алгоритм описанный выше:
void Table::myVPR()
{
if (!Table::readyDonor || !Table::readyRecepient)
{
statusBar->showMessage("Add Donor first, recepient second!", 2000);
return;
}
excelDonor = new QAxObject("Excel.Application", 0);
workbooksDonor = excelDonor->querySubObject("Workbooks");
workbookDonor = workbooksDonor->querySubObject("Open(const QString&)", addFileDonor);
sheetsDonor = workbookDonor->querySubObject("Worksheets");
sheetDonor = sheetsDonor->querySubObject("Item(int)", listDonor);
excelRecepient = new QAxObject("Excel.Application", 0);
workbooksRecepient = excelRecepient->querySubObject("Workbooks");
workbookRecepient = workbooksRecepient->querySubObject("Open(const QString&)", addFileRecepient);
sheetsRecepient = workbookRecepient->querySubObject("Worksheets");
sheetRecepient = sheetsRecepient->querySubObject("Item(int)", listRecepient);
QElapsedTimer timer;
int countTimer = 0;
timer.start();
QAxObject* copy = nullptr;
QAxObject* compareDonor = nullptr;
QAxObject* dayDonor = nullptr;
if (dayNightParametres)
{
QList<vprStruct> tabelDonorFindAndDay;
for (int counter = 1; counter <= countRowsDonor; counter++)
{
compareDonor = sheetDonor->querySubObject("Cells(auto,auto)", counter, memberWhatFind);
copy = sheetDonor->querySubObject("Cells(auto,auto)", counter, memberWhatToInsert);
dayDonor = sheetDonor->querySubObject("Cells(auto,auto)", counter, memberwhereDayNightDonor);
QVariant val1 = compareDonor->property("Value").toString();
QVariant val2 = dayDonor->property("Value").toString();
QVariant val3 = copy->property("Value").toString();
vprStruct some = { val1, val2, val3 };
tabelDonorFindAndDay.append(some);
delete compareDonor;
delete copy;
delete dayDonor;
}
workbookDonor->dynamicCall("Close()"); // обязательно используем в работе с Excel иначе документы будет фbоном открыт в системе
excelDonor->dynamicCall("Quit()");
delete workbookDonor;
delete excelDonor;
QAxObject* compareRecepient = nullptr;
QAxObject* paste = nullptr;
QAxObject* dayRecepient = nullptr;
QListIterator<vprStruct> it(tabelDonorFindAndDay);
int countDoingIterationForTime = 0;
for (int counter = 1; counter <= countRowsRecepient; counter++)
{
compareRecepient = sheetRecepient->querySubObject("Cells(&int,&int)", counter, memberWhereFind);
paste = sheetRecepient->querySubObject("Cells(&int,&int)", counter, memberWhereToInsert);
dayRecepient = sheetRecepient->querySubObject("Cells(&int,&int)", counter, memberwhereDayNightRecepient);
while (it.hasNext())
{
vprStruct temporary = it.next();
if ((temporary.whatFindStruct == compareRecepient->property("Value").toString()) && (temporary.dayNightStruct == dayRecepient->property("Value").toString())) // надо сравнивать QVariant с переводом в QString иначе не сравнивает.
{
++countDoingIterationForTime;
paste->dynamicCall("SetValue(String)", temporary.valueStruct.toDouble());
delete compareRecepient;
delete paste;
delete dayRecepient;
break;
}
if (timer.elapsed() % 5000 == 0 )
{
QTime ct = QTime::currentTime(); // возвращаем текущее время
qDebug() << ct.toString() << " " << countDoingIterationForTime;
countDoingIterationForTime = 0;
}
}
it.toFront();
delete sheetRecepient;
delete sheetsRecepient;
sheetsRecepient = workbookRecepient->querySubObject("Worksheets");
sheetRecepient = sheetsRecepient->querySubObject("Item(int)", listRecepient);
}
countTimer = timer.elapsed();
out << countTimer << Qt::endl;
workbookRecepient->dynamicCall("Close()");
excelRecepient->dynamicCall("Quit()");
delete workbookRecepient;
delete excelRecepient;
}
}
Ответы (1 шт):
Решил выложить решение спустя время. Вдруг кому пригодится.
Используя QMultiHash
и его метод find()
, можно получить iterator
, который указывает на искомое значение, если такое было найдено.
Если нет, то возвращает end()
- воображаемый элемент после последнего элемента в хэше.
Прирост в скорости выполнения - x20. Без потери количества итераций за единицу времени.
if (dayNightParametres)
{
QMultiHash<QPair<QString, QString>, QVariant> tabelDonorFindAndDay;
for (int counter = memberRowFromFindDonor; counter <= (countRowsDonor - lastLineDonor); counter++)`введите сюда код`
{
compareDonor = sheetDonor->querySubObject("Cells(auto,auto)", counter, memberWhatFind);
dayDonor = sheetDonor->querySubObject("Cells(auto,auto)", counter, memberwhereDayNightDonor);
copy = sheetDonor->querySubObject("Cells(auto,auto)", counter, memberWhatToInsert);
tabelDonorFindAndDay.insert(
QPair<QString,
QString>{
compareDonor->property("Value").toString(),
dayDonor->property("Value").toString()
},
copy->property("Value").toString());
delete compareDonor;
delete copy;
delete dayDonor;
}
workbookDonor->dynamicCall("Close()");
excelDonor->dynamicCall("Quit()");
delete workbookDonor;
delete excelDonor;
QMultiHashIterator<QPair<QString, QString>, QVariant> it(tabelDonorFindAndDay);
for (int counter = memberRowFromFindRecepient; counter <= (countRowsRecepient - lastLineRecepient); counter++)
{
compareRecepient = sheetRecepient->querySubObject("Cells(&int,&int)", counter, memberWhereFind);
paste = sheetRecepient->querySubObject("Cells(&int,&int)", counter, memberWhereToInsert);
dayRecepient = sheetRecepient->querySubObject("Cells(&int,&int)", counter, memberwhereDayNightRecepient);
negativeValue = sheetRecepient->querySubObject("Cells(&int,&int)", counter, colorColumnRecepint);
QPair <QString, QString> forFind{
compareRecepient->property("Value").toString(),
dayRecepient->property("Value").toString()};
if (tabelDonorFindAndDay.find(forFind) != tabelDonorFindAndDay.constEnd())
{
++countDoingIterationForTime;
paste->dynamicCall("SetValue(double)", (tabelDonorFindAndDay.find(forFind).value()));
// tabelDonorFindAndDay.remove(it.key(), it.value()); // удаление записей из хэша (непомогло ускорить процесс)
// tabelDonorFindAndDay.count(); - для подсчёта остатков после удаления из хэша записей
delete compareRecepient;
delete paste;
delete dayRecepient;
if (colorChecked)
{
if (negativeValue->property("Value").toDouble() < 0)
{
// получаем указатель на её фон
QAxObject* interior = negativeValue->querySubObject("Interior");
// устанавливаем цвет
interior->setProperty("Color", QColor("red"));
delete interior;
}
}
delete negativeValue;
}
delete sheetRecepient;
delete sheetsRecepient;
sheetsRecepient = workbookRecepient->querySubObject("Worksheets");
sheetRecepient = sheetsRecepient->querySubObject("Item(int)", listRecepient);
}
}