Постепенное замедление записи в Excel из QList

Программа выполняет выгрузку данных из одного Excel в массив строк QList (1-ый Excel закрывается). Затем последовательно двигаясь по второму файлу Excel,производит запись во второй Excel, при условии совпадения двух 2-х пар значений между сравниваемой ячейкой в Excel и одним из элементов массива QList.Проблема в том что происходит последовательное замедление выполнения программы. Вначале быстро стартует затем скорость постепенно падает. Отмерял количество записей в Excel каждые 5 секунд. Средний результат:

Время (+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 шт):

Автор решения: Anatoly

Решил выложить решение спустя время. Вдруг кому пригодится.

Используя 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);
    }
}
→ Ссылка