QT5.15.2使用QXlsx读取Excel文件后退出程序时程序异常结束
这是一个困扰了我很久的问题,今天终于解决啦。
异常场景
我的情况是只要用了QXlsx去操作Excel文件后,在关闭程序时无法正常退出程序,会卡住,过一会后在QT的IDE上显示程序异常结束。
解决方法
主要原因在于QXlsx源码的xlsxcellreference.cpp
中,
我们只需要找到void CellReference::init(const QString &cell_str)
方法,把static thread_local QRegularExpression re(QStringLiteral("^\\$?([A-Z]{1,3})\\$?(\\d+)$"));
的thread_local
修饰删掉,或者改成这样:
void CellReference::init(const QString &cell_str)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
static QRegularExpression re(QStringLiteral("^\\$?([A-Z]{1,3})\\$?(\\d+)$"));
QRegularExpressionMatch match = re.match(cell_str);
if (match.hasMatch())
{
const QString col_str = match.captured(1);
const QString row_str = match.captured(2);
_row = row_str.toInt();
_column = col_from_name(col_str);
}
#else
QRegExp re(QLatin1String("^\\$?([A-Z]{1,3})\\$?(\\d+)$"));
if (re.indexIn(cell_str) != -1)
{
const QString col_str = re.cap(1);
const QString row_str = re.cap(2);
_row = row_str.toInt();
_column = col_from_name(col_str);
}
#endif
}
然后再找到QString col_to_name(int col_num)
方法,同样的把static thread_local QMap<int, QString> col_cache;
的thread_local
修饰删掉:
QString col_to_name(int col_num)
{
static QMap<int, QString> col_cache;
auto it = col_cache.find(col_num);
if (it == col_cache.end()) {
QString col_str;
int remainder;
while (col_num) {
remainder = col_num % 26;
if (remainder == 0)
remainder = 26;
col_str.prepend(QChar('A' + remainder - 1));
col_num = (col_num - 1) / 26;
}
it = col_cache.insert(col_num, col_str);
}
return it.value();
}
保存后重新编译就行了,这样就能正常退出程序了
参考资料
其实QXlsx已经修复了这个问题,是因为我那个版本还存在这个问题而已,github的issues中就有了
https://github.com/QtExcel/QXlsx/issues/156
https://github.com/QtExcel/QXlsx/issues/153