0
0
mirror of https://github.com/fralx/LimeReport.git synced 2024-12-25 00:54:39 +03:00

xlsx exporter has been added

This commit is contained in:
Arin Alexander 2019-11-19 23:04:04 +03:00
parent 674528b095
commit c83da367a9
14 changed files with 406 additions and 11 deletions

View File

@ -1,4 +1,5 @@
#BINARY_RESULT_DIR = $${TOP_BUILD_DIR} #BINARY_RESULT_DIR = $${TOP_BUILD_DIR}
CONFIG *= qtxlsx
isEmpty(BINARY_RESULT_DIR) { isEmpty(BINARY_RESULT_DIR) {
BINARY_RESULT_DIR = $${PWD} BINARY_RESULT_DIR = $${PWD}

View File

@ -53,6 +53,7 @@ public slots:
void print(); void print();
void printToPDF(); void printToPDF();
void printToExcel();
void pageNavigatorChanged(int value); void pageNavigatorChanged(int value);
void saveToFile(); void saveToFile();
void setScalePercent(int percent); void setScalePercent(int percent);

View File

@ -0,0 +1,268 @@
#include "lrexcelexporter.h"
#include "lrtextitem.h"
#include "lrimageitem.h"
#include "lrshapeitem.h"
#include "lrexportersfactory.h"
#include "lrreportengine_p.h"
namespace{
LimeReport::ReportExporterInterface* createExcelExporter(LimeReport::ReportEnginePrivate* parent){
return new LimeReport::ExcelExporter(parent);
}
bool VARIABLE_IS_NOT_USED registred = LimeReport::ExportersFactory::instance().registerCreator("XLSX", LimeReport::ExporterAttribs(QObject::tr("Export to xlsx"), "XLSXExporter"), createExcelExporter);
}
namespace LimeReport{
ExcelExporter::ExcelExporter(ReportEnginePrivate *parent)
:QObject(parent)
{
exportedTypes << "ImageItem" << "TextItem";
}
QString ExcelExporter::exporterName()
{
return QObject::tr("XLSX");
}
QString ExcelExporter::exporterFileExt()
{
return "xlsx";
}
QString ExcelExporter::hint()
{
return QObject::tr("Export report to xlsx");
}
bool ExcelExporter::exportPages(ReportPages pages, const QString &fileName, const QMap<QString, QVariant> &params)
{
double xSizeFactor = params["xSizeFactor"].isNull() ? 2 : params["xSizeFactor"].toDouble();
double ySizeFactor = params["ySizeFactor"].isNull() ? 0.37 : params["ySizeFactor"].toDouble();
if (pages.isEmpty()) return false;
m_document = new QXlsx::Document();
x.clear();
y.clear();
Grid grid;
if ((pages.size() > 1) && (pages[0]->pos() == pages[1]->pos()) ){
int curHeight = 0;
foreach(PageItemDesignIntf::Ptr pageItem, pages){
pageItem->setPos(0,curHeight);
curHeight+=pageItem->height();
}
}
foreach(PageItemDesignIntf::Ptr page, pages){
buildGrid(&grid,page.data());
}
foreach (qreal value, grid.x.values()) {
x.append(value);
}
foreach (qreal value, grid.y.values()) {
y.append(value);
}
std::sort(x.begin(), x.end());
std::sort(y.begin(), y.end());
m_yOffset = 0;
m_xOffset = 0;
m_document->setTopPageMargin(pages.first()->topMargin()/25.4);
m_document->setLeftPageMargin(pages.first()->leftMargin()/25.4);
m_document->setRightPageMargin(pages.first()->rightMargin()/25.4);
m_document->setBottomPageMargin(pages.first()->bottomMargin()/25.4);
for(int i = 0; i<x.size(); ++i){
if ( i == 0 ){
if (x[i] > 0){
qreal columnWidth = x[i] - pages.at(0)->leftMargin();
if (columnWidth>0){
m_document->setColumnWidth(i+1, columnWidth / xSizeFactor);
m_xOffset = 1;
}
}
} else {
m_document->setColumnWidth(i+1, (x[i]-x[i-1]) / xSizeFactor);
}
}
for(int i = 0; i<y.size(); ++i){
if ( i == 0 ) {
if (y[i] > 0){
qreal rowHeight = y[i] - pages.at(0)->topMargin();
if (rowHeight > 0){
m_document->setRowHeight(i+1, rowHeight / ySizeFactor);
m_yOffset = 1;
}
}
} else {
m_document->setRowHeight(i+1, (y[i]-y[i-1]) / ySizeFactor);
}
}
foreach(PageItemDesignIntf::Ptr page, pages){
exportItem(page.data());
}
return m_document->saveAs(fileName);
}
void ExcelExporter::buildGrid(Grid *grid, BaseDesignIntf *item)
{
foreach (BaseDesignIntf* child, item->childBaseItems()) {
if (child->canContainChildren())
buildGrid(grid, child);
else{
if (exportedTypes.contains(child->storageTypeName())){
grid->x.insert(child->getAbsolutePosX());
grid->x.insert(child->getAbsolutePosX()+child->getItemWidth());
grid->y.insert(child->getAbsolutePosY());
grid->y.insert(child->getAbsolutePosY()+child->getItemHeight());
}
}
}
}
void ExcelExporter::exportItem(BaseDesignIntf *item)
{
if (item->canContainChildren()){
foreach (BaseDesignIntf* child, item->childBaseItems()){
exportItem(child);
}
} else {
createItemCell(item);
}
}
QXlsx::Format ExcelExporter::createTextItemFormat(BaseDesignIntf* item){
TextItem* textItem = dynamic_cast<TextItem*>(item);
QXlsx::Format format;
format.setTextWarp(true);
// format.setFontName(item->font().family());
// format.setFontBold(item->font().bold());
// format.setFontItalic(item->font().italic());
// format.setFontUnderline(item->font().underline() ? QXlsx::Format::FontUnderlineSingle : QXlsx::Format::FontUnderlineNone);
// format.setFontSize(item->font().pointSize());
format.setFont(item->font());
// format.setFontSize(item->font().pointSize()-1);
format.setFontColor(item->fontColor());
format.setFillPattern(QXlsx::Format::PatternSolid);
format.setPatternBackgroundColor(item->backgroundColor());
format.setBorderColor(item->borderColor());
if (item->borderLines() & BaseDesignIntf::TopLine){
format.setTopBorderStyle(QXlsx::Format::BorderThin);
}
if (item->borderLines() & BaseDesignIntf::RightLine){
format.setRightBorderStyle(QXlsx::Format::BorderThin);
}
if (item->borderLines() & BaseDesignIntf::LeftLine){
format.setLeftBorderStyle(QXlsx::Format::BorderThin);
}
if (item->borderLines() & BaseDesignIntf::BottomLine){
format.setBottomBorderStyle(QXlsx::Format::BorderThin);
}
if (textItem->alignment() & Qt::AlignLeft){
format.setHorizontalAlignment(QXlsx::Format::AlignLeft);
}
if (textItem->alignment() & Qt::AlignRight){
format.setHorizontalAlignment(QXlsx::Format::AlignRight);
}
if (textItem->alignment() & Qt::AlignHCenter){
format.setHorizontalAlignment(QXlsx::Format::AlignHCenter);
}
if (textItem->alignment() & Qt::AlignTop){
format.setVerticalAlignment(QXlsx::Format::AlignTop);
}
if (textItem->alignment() & Qt::AlignBottom){
format.setVerticalAlignment(QXlsx::Format::AlignBottom);
}
if (textItem->alignment() & Qt::AlignVCenter){
format.setVerticalAlignment(QXlsx::Format::AlignVCenter);
}
return format;
}
void ExcelExporter::createItemCell(BaseDesignIntf *item)
{
int startColumnIndex = cellStartColumnIndex(item);
int endColumnIndex = cellEndColumnIndex(item);
int startRowIndex = cellStartRowIndex(item);
int endRowIndex = cellEndRowIndex(item);
bool needMerge = (endColumnIndex - startColumnIndex > 1) || (endRowIndex - startRowIndex > 1);
QXlsx::Format format;
if (item->storageTypeName().compare("TextItem") == 0){
TextItem* ci = dynamic_cast<TextItem*>(item);
format = createTextItemFormat(item);
m_document->write(startRowIndex, startColumnIndex, ci->content(), format);
if (needMerge)
m_document->mergeCells(QXlsx::CellRange(startRowIndex, startColumnIndex, endRowIndex-1, endColumnIndex-1), format);
} else if (item->storageTypeName().compare("ImageItem") == 0){
LimeReport::ImageItem* ii = dynamic_cast<ImageItem*>(item);
QImage img = ii->image().scaled(item->width()/3,item->height()/3, Qt::KeepAspectRatio);
m_document->insertImage(startRowIndex-1, startColumnIndex, img);
if (needMerge)
m_document->mergeCells(QXlsx::CellRange(startRowIndex, startColumnIndex, endRowIndex-1, endColumnIndex-1), format);
} else {
//m_document->write(startRowIndex, startColumnIndex, item->objectName());
}
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
int ExcelExporter::cellStartColumnIndex(BaseDesignIntf *item)
{
for(int i = 1; i <= x.size(); ++i){
if (x[i-1] == item->getAbsolutePosX()) return i + m_xOffset;
}
return -1;
}
int ExcelExporter::cellEndColumnIndex(BaseDesignIntf *item)
{
for(int i = 1; i <= x.size(); ++i){
if (x[i-1] == (item->getAbsolutePosX() + item->getItemWidth()) ) return i + m_xOffset;
}
return -1;
}
int ExcelExporter::cellStartRowIndex(BaseDesignIntf *item)
{
for(int i = 1; i <= y.size(); ++i){
if (y[i-1] == item->getAbsolutePosY()) return i + m_yOffset;
}
return -1;
}
int ExcelExporter::cellEndRowIndex(BaseDesignIntf *item)
{
for(int i = 1; i <= y.size(); ++i){
if (y[i-1] == (item->getAbsolutePosY() + item->getItemHeight()) ) return i + m_yOffset;
}
return -1;
}
#pragma clang diagnostic pop
} //namespace LimeReport

View File

@ -0,0 +1,49 @@
#ifndef LREXCELEXPORTER_H
#define LREXCELEXPORTER_H
#include <QSet>
#include <xlsxdocument.h>
#include "lrexporterintf.h"
namespace LimeReport{
struct Grid{
QSet<qreal> x;
QSet<qreal> y;
};
class ExcelExporter : public QObject, public ReportExporterInterface{
Q_OBJECT
public:
ExcelExporter(ReportEnginePrivate *parent = 0);
// IReportExporter interface
QString exporterName();
QString exporterFileExt();
QString hint();
bool exportPages(ReportPages pages, const QString& fileName, const QMap<QString, QVariant>& params = QMap<QString, QVariant>());
private:
void buildGrid(Grid* grid, BaseDesignIntf* item);
void exportItem(BaseDesignIntf* item);
void createItemCell(BaseDesignIntf* item);
int cellStartColumnIndex(BaseDesignIntf* item);
int cellEndColumnIndex(BaseDesignIntf* item);
int cellStartRowIndex(BaseDesignIntf* item);
int cellEndRowIndex(BaseDesignIntf* item);
QXlsx::Format createTextItemFormat(BaseDesignIntf *item);
private:
QVector<qreal>x;
QVector<qreal>y;
QVector<QString> exportedTypes;
int m_xOffset;
int m_yOffset;
QXlsx::Document* m_document;
};
} //namespace LimeReport
#endif // LREXCELEXPORTER_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,5 +1,10 @@
include(../common.pri) include(../common.pri)
contains(CONFIG, qtxlsx){
DEFINES += HAVE_QTXLSX
include($$PWD/../3rdparty/qtxlsx/src/xlsx/qtxlsx.pri)
}
contains(CONFIG, embedded_designer){ contains(CONFIG, embedded_designer){
include(designer.pri) include(designer.pri)
} }
@ -69,9 +74,9 @@ SOURCES += \
$$REPORT_PATH/items/lrchartitemeditor.cpp \ $$REPORT_PATH/items/lrchartitemeditor.cpp \
$$REPORT_PATH/lrreporttranslation.cpp \ $$REPORT_PATH/lrreporttranslation.cpp \
$$REPORT_PATH/exporters/lrpdfexporter.cpp \ $$REPORT_PATH/exporters/lrpdfexporter.cpp \
$$REPORT_PATH/exporters/lrhtmlexporter.cpp \
$$REPORT_PATH/lrpreparedpages.cpp $$REPORT_PATH/lrpreparedpages.cpp
contains(CONFIG, staticlib){ contains(CONFIG, staticlib){
SOURCES += $$REPORT_PATH/lrfactoryinitializer.cpp SOURCES += $$REPORT_PATH/lrfactoryinitializer.cpp
} }
@ -80,6 +85,11 @@ contains(CONFIG, zint){
SOURCES += $$REPORT_PATH/items/lrbarcodeitem.cpp SOURCES += $$REPORT_PATH/items/lrbarcodeitem.cpp
} }
contains(CONFIG, qtxlsx){
message(QtXLSX)
SOURCES += $$REPORT_PATH/exporters/lrexcelexporter.cpp
}
HEADERS += \ HEADERS += \
$$REPORT_PATH/base/lrsingleton.h \ $$REPORT_PATH/base/lrsingleton.h \
$$REPORT_PATH/base/lrsimpleabstractfactory.h \ $$REPORT_PATH/base/lrsimpleabstractfactory.h \
@ -154,10 +164,10 @@ HEADERS += \
$$REPORT_PATH/lrexporterintf.h \ $$REPORT_PATH/lrexporterintf.h \
$$REPORT_PATH/lrexportersfactory.h \ $$REPORT_PATH/lrexportersfactory.h \
$$REPORT_PATH/exporters/lrpdfexporter.h \ $$REPORT_PATH/exporters/lrpdfexporter.h \
$$REPORT_PATH/exporters/lrhtmlexporter.h \
$$REPORT_PATH/lrpreparedpages.h \ $$REPORT_PATH/lrpreparedpages.h \
$$REPORT_PATH/lrpreparedpagesintf.h $$REPORT_PATH/lrpreparedpagesintf.h
contains(CONFIG, staticlib){ contains(CONFIG, staticlib){
HEADERS += $$REPORT_PATH/lrfactoryinitializer.h HEADERS += $$REPORT_PATH/lrfactoryinitializer.h
} }
@ -166,6 +176,10 @@ contains(CONFIG,zint){
HEADERS += $$REPORT_PATH/items/lrbarcodeitem.h HEADERS += $$REPORT_PATH/items/lrbarcodeitem.h
} }
contains(CONFIG, qtxlsx){
HEADERS += $$REPORT_PATH/exporters/lrexcelexporter.h
}
FORMS += \ FORMS += \
$$REPORT_PATH/lrpreviewreportwindow.ui \ $$REPORT_PATH/lrpreviewreportwindow.ui \
$$REPORT_PATH/lrpreviewreportwidget.ui \ $$REPORT_PATH/lrpreviewreportwidget.ui \

View File

@ -40,8 +40,7 @@ EXTRA_FILES += \
$$PWD/lrscriptenginemanagerintf.h \ $$PWD/lrscriptenginemanagerintf.h \
$$PWD/lrcallbackdatasourceintf.h \ $$PWD/lrcallbackdatasourceintf.h \
$$PWD/lrpreviewreportwidget.h \ $$PWD/lrpreviewreportwidget.h \
$$PWD/lrreportdesignwindowintrerface.h \ $$PWD/lrreportdesignwindowintrerface.h
$$PWD/lrpreparedpagesintf.h
include(limereport.pri) include(limereport.pri)
@ -112,14 +111,14 @@ INSTALLS += target
####Automatically build required translation files (*.qm) ####Automatically build required translation files (*.qm)
contains(CONFIG,build_translations){ contains(CONFIG,build_translations){
LANGUAGES = ru es ar fr zh pl LANGUAGES = ru es_ES ar fr zh
defineReplace(prependAll) { defineReplace(prependAll) {
for(a,$$1):result += $$2$${a}$$3 for(a,$$1):result += $$2$${a}$$3
return($$result) return($$result)
} }
TRANSLATIONS = $$prependAll(LANGUAGES, $$TRANSLATIONS_PATH/limereport_,.ts) TRANSLATIONS = $$prependAll(LANGUAGES, \"$$TRANSLATIONS_PATH/limereport_,.ts\")
qtPrepareTool(LUPDATE, lupdate) qtPrepareTool(LUPDATE, lupdate)
@ -133,7 +132,7 @@ lessThan(QT_MAJOR_VERSION, 5){
qtPrepareTool(LRELEASE, lrelease) qtPrepareTool(LRELEASE, lrelease)
for(tsfile, TRANSLATIONS) { for(tsfile, TRANSLATIONS) {
qmfile = $$tsfile qmfile = $$tsfile
qmfile ~= s,".ts$",".qm", qmfile ~= s,".ts\"$",".qm\"",
qm.commands += $$LRELEASE -removeidentical $$tsfile -qm $$qmfile $$escape_expand(\\n\\t) qm.commands += $$LRELEASE -removeidentical $$tsfile -qm $$qmfile $$escape_expand(\\n\\t)
tmp_command = $$LRELEASE -removeidentical $$tsfile -qm $$qmfile $$escape_expand(\\n\\t) tmp_command = $$LRELEASE -removeidentical $$tsfile -qm $$qmfile $$escape_expand(\\n\\t)
TRANSLATIONS_FILES += $$qmfile TRANSLATIONS_FILES += $$qmfile

View File

@ -45,6 +45,10 @@
#include "lrexporterintf.h" #include "lrexporterintf.h"
#include "exporters/lrpdfexporter.h" #include "exporters/lrpdfexporter.h"
#ifdef HAVE_QTXLSX
#include "exporters/lrexcelexporter.h"
#endif
void initResources(){ void initResources(){
Q_INIT_RESOURCE(report); Q_INIT_RESOURCE(report);
#ifdef HAVE_REPORT_DESIGNER #ifdef HAVE_REPORT_DESIGNER
@ -450,6 +454,12 @@ LimeReport::ReportExporterInterface* createPDFExporter(ReportEnginePrivate* pare
return new LimeReport::PDFExporter(parent); return new LimeReport::PDFExporter(parent);
} }
#ifdef HAVE_QTXLSX
LimeReport::ReportExporterInterface* createExcelExporter(ReportEnginePrivate* parent){
return new LimeReport::ExcelExporter(parent);
}
#endif
void initExporters() void initExporters()
{ {
ExportersFactory::instance().registerCreator( ExportersFactory::instance().registerCreator(
@ -457,6 +467,14 @@ void initExporters()
LimeReport::ExporterAttribs(QObject::tr("Export to PDF"), "PDFExporter"), LimeReport::ExporterAttribs(QObject::tr("Export to PDF"), "PDFExporter"),
createPDFExporter createPDFExporter
); );
#ifdef HAVE_QTXLSX
ExportersFactory::instance().registerCreator(
"XLSX",
LimeReport::ExporterAttribs(QObject::tr("Export to xlsx"),"ExcelExporter"),
createExcelExporter
);
#endif
} }
} //namespace LimeReport } //namespace LimeReport

View File

@ -258,6 +258,16 @@ void PreviewReportWidget::print()
} }
void PreviewReportWidget::printToExcel()
{
if (!d_ptr->m_reportPages.isEmpty()){
exportReport("XLSX");
foreach(PageItemDesignIntf::Ptr pageItem, d_ptr->m_reportPages){
d_ptr->m_previewPage->reactivatePageItem(pageItem);
}
}
}
void PreviewReportWidget::printToPDF() void PreviewReportWidget::printToPDF()
{ {
if (!d_ptr->m_reportPages.isEmpty()){ if (!d_ptr->m_reportPages.isEmpty()){

View File

@ -53,6 +53,7 @@ public slots:
void print(); void print();
void printToPDF(); void printToPDF();
void printToExcel();
void pageNavigatorChanged(int value); void pageNavigatorChanged(int value);
void saveToFile(); void saveToFile();
void setScalePercent(int percent); void setScalePercent(int percent);

View File

@ -468,6 +468,11 @@ void PreviewReportWindow::slotPrintToPDF()
m_previewReportWidget->printToPDF(); m_previewReportWidget->printToPDF();
} }
void PreviewReportWindow::slotPrintToExcel()
{
m_previewReportWidget->printToExcel();
}
void PreviewReportWindow::slotPageChanged(int pageIndex) void PreviewReportWindow::slotPageChanged(int pageIndex)
{ {
m_pagesNavigator->setValue(pageIndex); m_pagesNavigator->setValue(pageIndex);

View File

@ -105,6 +105,7 @@ public slots:
void slotFirstPage(); void slotFirstPage();
void slotLastPage(); void slotLastPage();
void slotPrintToPDF(); void slotPrintToPDF();
void slotPrintToExcel();
void slotPageChanged(int pageIndex); void slotPageChanged(int pageIndex);
void slotInsertNewTextItem(); void slotInsertNewTextItem();
void slotActivateItemSelectionMode(); void slotActivateItemSelectionMode();

View File

@ -35,7 +35,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>800</width>
<height>20</height> <height>22</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuView"> <widget class="QMenu" name="menuView">
@ -78,6 +78,7 @@
<addaction name="actionEdit_Mode"/> <addaction name="actionEdit_Mode"/>
<addaction name="actionSaveToFile"/> <addaction name="actionSaveToFile"/>
<addaction name="actionPrint_To_PDF"/> <addaction name="actionPrint_To_PDF"/>
<addaction name="actionactionPrintToExcel"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionZoomIn"/> <addaction name="actionZoomIn"/>
<addaction name="actionZoomOut"/> <addaction name="actionZoomOut"/>
@ -339,14 +340,23 @@
<string>Del</string> <string>Del</string>
</property> </property>
</action> </action>
<action name="actionactionPrintToExcel">
<property name="icon">
<iconset resource="report.qrc">
<normaloff>:/report/images/excel_export.png</normaloff>:/report/images/excel_export.png</iconset>
</property>
<property name="text">
<string>actionPrintToExcel</string>
</property>
<property name="toolTip">
<string>Export report to Excel</string>
</property>
</action>
</widget> </widget>
<resources> <resources>
<include location="report.qrc"/> <include location="report.qrc"/>
<include location="items/items.qrc"/> <include location="items/items.qrc"/>
<include location="databrowser/lrdatabrowser.qrc"/> <include location="databrowser/lrdatabrowser.qrc"/>
<include location="report.qrc"/>
<include location="items/items.qrc"/>
<include location="databrowser/lrdatabrowser.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>
@ -541,6 +551,22 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>actionactionPrintToExcel</sender>
<signal>triggered()</signal>
<receiver>LimeReport::PreviewReportWindow</receiver>
<slot>slotPrintToExcel()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
</connections> </connections>
<slots> <slots>
<slot>slotNextPage()</slot> <slot>slotNextPage()</slot>
@ -554,5 +580,6 @@
<slot>slotInsertNewTextItem()</slot> <slot>slotInsertNewTextItem()</slot>
<slot>slotActivateItemSelectionMode()</slot> <slot>slotActivateItemSelectionMode()</slot>
<slot>slotDeleteSelectedItems()</slot> <slot>slotDeleteSelectedItems()</slot>
<slot>slotPrintToExcel()</slot>
</slots> </slots>
</ui> </ui>

View File

@ -186,5 +186,6 @@
<file alias="/images/logo32">images/designer.png</file> <file alias="/images/logo32">images/designer.png</file>
<file alias="/images/lock">images/lock.png</file> <file alias="/images/lock">images/lock.png</file>
<file>images/unlock.png</file> <file>images/unlock.png</file>
<file>images/excel_export.png</file>
</qresource> </qresource>
</RCC> </RCC>