我有一个程序,可以一次读取每个单元格,逐行迭代,从而将excel转换为数据。

为此,我一直在使用两个单独的库:

ExcelFormat (for xls)

Xlsx I/O

我有一个算法的抽象类,每个都有两个派生类。我遇到的问题是ExcelFormat和Xlsx I / O不遵循相同的格式(因为它们是独立的库,并且不遵循相同的基类)。

(请注意,我为xlsxio编写了一个包装程序,因为它是程序性的,并且我需要OO功能)

我想将算法尽可能抽象为基类。

就目前而言,我真正能够做的就是拥有通用的抽象方法Convert(),该方法非常差,因为这两个函数在算法上都非常相似,但是仅由于它们无法遵循统一的接口不要共享相同的基础。

这是我所拥有的:

bool XlsxToData::Convert(const std::string & filePath, std::list<SqlParam*>* params) {
    FreeXlsx::XlsxBook book(filePath);

    if (book.IsOpen()) {

        std::vector<std::string>* sheets = book.GetSheetList();
        if (sheets != nullptr) {
            std::list<SqlParam*> foundParams;

            for (auto itr : *sheets) {

                FreeXlsx::XlsxSheet sheet(itr, book);

                std::map<int, SqlParam*> foundX;

                int longestWidth = 0;
                int lastWidth = 0;

                if (sheet.IsOpen()) {

                    sheet.ForSheet([this, &foundParams, &foundX, &longestWidth, &lastWidth, params](const std::string & value, const int & x, const int & y) {
                        if (x > longestWidth)
                            longestWidth = x;

                        lastWidth = x;

                        GetValueCell(foundX, value, x);

                        CheckParams(foundX, foundParams, value, x, params);
                    },
                        [&longestWidth, &lastWidth, &foundX, this](const int & row) {

                        if (lastWidth < longestWidth)
                            for (int i = lastWidth + 1; i <= longestWidth; ++i) {
                                auto find = foundX.find(i);

                                if (find != foundX.end()) {

                                    find->second->PushValue("");
                                }
                            }

                    });

                    sheet.Close();
                }

                if (params->size() < 1)
                    break;
            }

            delete sheets;

            while (foundParams.size() > 0) {
                params->push_back(*foundParams.begin());
                foundParams.erase(foundParams.begin());
            }

        }

        book.Close();

        return true;
    }

    return false;
}

bool XlsToData::Convert(const std::string & filePath, std::list<SqlParam*>* params) {
    ExcelFormat::BasicExcel book;

    if (book.Load(filePath.c_str())) {
        int sheets = book.GetTotalWorkSheets();
        std::list<SqlParam*> foundParams;

        for (int i = 0; i < sheets; ++i) {
            ExcelFormat::BasicExcelWorksheet* sheet = book.GetWorksheet(i);

            std::map<int, SqlParam*> foundX;

            if (sheet != nullptr) {
                const int rows = sheet->GetTotalRows();
                const int cols = sheet->GetTotalCols();

                std::map<int, SqlParam*> foundX;

                for (int row = 0; row < rows; ++row) {
                    bool willBreak = false;

                    for (int col = 0; col < cols; ++col) {
                        ExcelFormat::BasicExcelCell * cell = sheet->Cell(row, col);

                        if (cell != nullptr) {
                            std::string value = getval(cell);

                            GetValueCell(foundX, value, col);

                            CheckParams(foundX, foundParams, value, col, params);
                        }

                    }

                    if (willBreak)
                        break;
                }
            }
        }

        while (foundParams.size() > 0) {
            params->push_back(*foundParams.begin());
            foundParams.erase(foundParams.begin());
        }

        book.Close();

        return true;
    }

    return false;
}


我希望能够将打开书/表格的方法抽象为单个方法,作为迭代每个单元格的过程。

我已经考虑过可能为Xlsx I / O修改ExcelFormat和Wrapper类的源,以使其与统一的抽象库一起使用。

这将是最明智的方法吗?

是否已经有针对此类冲突的设计模式?

我是否应该实现一个继承自Excel Format的类的适配器类,然后使Xlsxio包装器和新的适配器类符合新的抽象基础?

还是有人有更好的解决方案?

谢谢。

编辑:另外,请注意,我意识到这显然具有较长的方法代码气味。我打算用更通用的算法来重构它。

最佳答案

您是否考虑过使用https://sourceforge.net/projects/xlslib/
它稍微过时了,更便于携带。

对于XLSX I / O,如果您需要遍历包括空单元格在内的所有单元格,则建议为xlsxioread_process使用XLSXIOREAD_SKIP_NONE标志。

对于其余的部分,由于库之间的方法不同,我认为编写一个通用的基类并不像您所说的那样显而易见。

我的建议是使抽象类尽可能抽象,这意味着您不应基于任何一个库,而应基于它们的公共属性。

我个人已经放弃了.xls支持,因为这是Microsoft自Office 2007起就不再主动使用的封闭格式。

10-07 15:24