在诸多场合,需要离线分析excel表格或者xml,就需要把已经完成的程序从对接数据库改为对接xml或者excel表离线分析数据,这个时候,如果按照excel的改法去大改,耗时耗力,而且得不到好结果,这时候就需要直接分析sql语句,把sql语句与excel表关联起来。
实现思路大致为:所有逻辑运算符使用enum枚举将它们关系从一个运算符转为一个可以存储的类型或者变量。而嵌套关系,在存储的中间件中,则使用链表,可以指向本类的指针,来指向下一个节点或子节点,这样就可以无限指向子节点来维护各种深层次的嵌套关系。这样一个可以存储所有嵌套关系以及逻辑运算符的存储介质就有了。
接下来是关于实现思路,实现思路大致就是递归处理子节点,最外层只需要实现父节点的所有逻辑关系以及表达式,然后一直递归,递归到子节点指向NULL,则递归停止。所有逻辑关系运算最后打包成一个公式,比如1!=2、1<2、1==2||2<3&&3==3等这种公式(注意:逻辑&&比逻辑||优先级高),然后使用QJsEngine或者QJavaScriptEngine对接javaScript代码来运算逻辑表达式,从而返回筛选结果。
本章读取Excel使用了libxl,因为涉及到读取xls以及xlsx,这里实现可以使用其他中间件。直接贴出代码:
读取excel的关键类ReadWriteExcel
readwriteexcel.h
#ifndef READWRITEEXCEL_H
#define READWRITEEXCEL_H
#include <wchar.h>
#include <stdlib.h>
#include <iostream>
#include <QString>
#include "libxl.h"
#include <stdlib.h>
#include <QDebug>
#include <QQueue>
#include <QQmlEngine>
#include <QScriptEngine>
#include <QRegularExpression>
#include <stdio.h>
#include <functional>
#include "cdatetime.h"
using namespace libxl;
#ifdef _UNICODE
#define STR2CHAR(input) (QString(input).toStdWString().c_str())
#define CHAR2STR(input) (QString::fromWCharArray(input))
#else
#define STR2CHAR(input) (QString(input).toStdString().c_str())
#define CHAR2STR(input) (QString::fromLocal8Bit(input))
#endif
enum VSTATE{
DEFAULT,
EQUAL, //“==”等于
UNEQUAL, //“!=”不等
LIKE, //“Like”包含
IN, //满足一个则为true,值以“,”隔开
MORE, //“>”
LESS, //“<”
MOREEQUAL, //“>=”
LESSEQUAL, //“<=”
};
enum LOGICSTATE
{
AND,
OR
};
typedef struct
{
VSTATE v_state = VSTATE::DEFAULT;
QPair<QString,QVariant> valueMap;
// QVariant::Type str_type =QVariant::Invalid;
}VSTATESTR;
// 用于表示逻辑运算符和对应条件的结构体
struct LogicCond;
//把整个where语句串起来
typedef struct LogicCond{
VSTATESTR m_judege; // 本节点
struct LogicCond* subCondNext = NULL; // 如果本节点是列表,则为列表
LOGICSTATE logicState = LOGICSTATE::AND; // 与下一个LogicCondition的关系
// struct LogicCond * lastLogicCond = NULL; //上一个节点
struct LogicCond * nextLogicCond = NULL; //下一个节点
}LogicCondition;
enum DBTYPE
{
unkown,
UInt,
Int,
Double,
String,
Data,
DateTIme
};
class ReadWriteExcel
{
public:
ReadWriteExcel();
~ReadWriteExcel();
//打开文件
bool open(QString path);
//获取所有数据
QVector<QVector<QString> > GetAllData();
//传入规则树,传出匹配的行数
quint64 GetDataCount(LogicCondition logic);
quint64 GetDataCount(QMap<QString,DBTYPE> dbTypeMap,QString where_order);
QList<QVariantHash> GetData(QMap<QString,DBTYPE> dbTypeMap,QString where_order,QPair<QString,bool> orderBy);
QList<QVariantHash> GetData(QMap<QString,DBTYPE> dbTypeMap,QString where_order,QPair<QString,bool> orderBy,int index,int count);
LogicCondition *ConvertToLogicCondition(QMap<QString,DBTYPE> dbTypeMap, QString where_order, QMap<QString,QString> excelMap = QMap<QString,QString>());
void DeleteLogicCondition(LogicCondition* logic);
void DebugLogicCondition(LogicCondition* logic);
//关闭文件
void close();
private:
bool JudegeEvaluate(LogicCondition* logic, QMap<QString,QString> jedgeMap = QMap<QString,QString>());
bool JudegeEvaluate(VSTATESTR jedgeValue,QMap<QString,QString> jedgeMap = QMap<QString,QString>());
QString SplictOutermostBracket(QString text);
VSTATE GetState(QString str);
QList<QVariantHash> SortMapValues(QMultiMap<QString,QVariantHash> map,bool isGreater);
private:
Book* m_book{NULL};
QString m_path;
QScriptEngine engine;
};
#endif // READWRITEEXCEL_H
readwriteexcel.cpp
#include "readwriteexcel.h"
ReadWriteExcel::ReadWriteExcel()
{
m_book = xlCreateBook();
#ifdef Q_OS_WIN
m_book->setKey(STR2CHAR("GCCG"), STR2CHAR("windows-282123090cc0e6036db16b60a1q3q0i9"));
#else
book->setKey(STR2CHAR("libxl"), STR2CHAR("linux-i8i3ibi2i8i4iei3i9iaiei8ibx6x5i3"));
#endif
qRegisterMetaType<CDateTime>("CDateTime");
}
ReadWriteExcel::~ReadWriteExcel()
{
m_book->release();
}
bool ReadWriteExcel::open(QString path)
{
if(!m_book->load(STR2CHAR(path)))
{
qDebug()<<"load file error:"<<m_book->errorMessage();
return false;
}
m_path = path;
return true;
}
QVector<QVector<QString> > ReadWriteExcel::GetAllData()
{
QVector<QVector<QString> > resultList;
if(m_book->load(STR2CHAR(m_path)))
{
libxl::Sheet* sheet = m_book->getSheet(0); // 获取第一个工作表
if (sheet) {
int rowCount = sheet->lastRow(); // 获取行数
int colCount = sheet->lastCol(); // 获取列数
for (int row = 0; row <= rowCount; ++row) {
QVector<QString> resultTempList;
for (int col = 0; col <= colCount; ++col) {
libxl::CellType cellType = sheet->cellType(row, col); // 获取单元格类型
QString value = "";
if (cellType == libxl::CELLTYPE_NUMBER) {
value = QString::number(sheet->readNum(row, col)); // 读取数字类型单元格的值
}
else if (cellType == libxl::CELLTYPE_STRING) {
value = CHAR2STR(sheet->readStr(row, col)); // 读取字符串类型单元格的值
}
else {
}
resultTempList.push_back(value);
}
resultList.push_back(resultTempList);
}
}
// m_book->release(); // 释放Book对象
}
return resultList;
}
quint64 ReadWriteExcel::GetDataCount(LogicCondition logic)
{
// QVector<QVector<QString> > resultList;
quint64 count = 0;
if(m_book->load(STR2CHAR(m_path)))
{
libxl::Sheet* sheet = m_book->getSheet(0); // 获取第一个工作表
if (sheet) {
int rowCount = sheet->lastRow(); // 获取行数
int colCount = sheet->lastCol(); // 获取列数
QList<QString> headerList;
for (int row = 0; row <= rowCount; ++row) {
// QVector<QString> resultTempList;
QMap<QString,QString> value_map;
for (int col = 0; col <= colCount; &