1
0
mirror of https://github.com/QtExcel/QXlsx.git synced 2025-01-30 05:02:52 +08:00

move copycat to personal repository

This commit is contained in:
Jay Two 2019-09-19 22:53:15 +09:00
parent 8b0d3cf838
commit 4d849bf739
22 changed files with 8 additions and 1707 deletions

View File

@ -1,54 +0,0 @@
# Copycat.pro
TARGET = Copycat
TEMPLATE = app
QT += core
QT += gui
QT += widgets
QT += printsupport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# NOTE: You can fix value of QXlsx path of source code.
# QXLSX_PARENTPATH=./
# QXLSX_HEADERPATH=./header/
# QXLSX_SOURCEPATH=./source/
include(../QXlsx/QXlsx.pri)
INCLUDEPATH += \
./Qt-Table-Printer
HEADERS += \
./Qt-Table-Printer/tableprinter.h \
MainWindow.h \
XlsxTab.h \
xlsx.h \
CopycatTableModel.h \
XlsxTableWidget.h
SOURCES += \
./Qt-Table-Printer/tableprinter.cpp \
main.cpp \
MainWindow.cpp \
XlsxTab.cpp \
CopycatTableModel.cpp \
XlsxTableWidget.cpp
FORMS += \
MainWindow.ui
RESOURCES += \
resources.qrc

View File

@ -1,122 +0,0 @@
// CopycatTableModel.cpp
// QXlsx // MIT License // https://github.com/j2doll/QXlsx
#include "CopycatTableModel.h"
#include <QDebug>
#include <QVariant>
CopycatTableModel::CopycatTableModel(QList<QString> colTitle, QList<VLIST> data, QObject *parent)
: QAbstractTableModel(parent)
{
// [1] set name of column
for ( int ic = 0; ic < colTitle.size() ; ic++ )
{
std::string colString = convertFromNumberToExcelColumn( ic );
// QString strCol = colTitle.at(ic);
QString strCol = QString::fromStdString( colString );
m_colNames.append( strCol );
}
m_roleCount = m_colNames.size();
// [2] set data
for ( int dc = 0; dc < data.size() ; dc++ )
{
VLIST vList = data.at(dc);
m_the_data.append( vList );
}
}
int CopycatTableModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent)
return m_the_data.size();
}
int CopycatTableModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent)
return m_roleCount;
}
QVariant CopycatTableModel::data(const QModelIndex& index, int role) const
{
// current column & row
int col = index.column();
int row = index.row();
// check boudaries
if ( col < 0 || columnCount() <= col ||
row < 0 || rowCount() <= row )
{
qDebug() << "[Warning]" << " col=" << col << ", row=" << row;
return QVariant();
}
// Nominal case
QVariant ret;
int cmpRole;
for (int ic = 0; ic < m_the_data.size() ; ic++)
{
if ( row == ic )
{
QList<QVariant> vList = m_the_data.at(ic);
for (int jc = 0; jc < vList.size() ; jc++ )
{
if ( col == jc &&
row == ic )
{
QVariant var = vList.at(jc);
if ( ! var.isValid() )
var.setValue( QString("") ) ;
if ( var.isNull() )
var.setValue( QString("") ) ;
ret = var;
}
}
}
}
return ret;
}
std::string CopycatTableModel::convertFromNumberToExcelColumn(int n)
{
// main code from https://www.geeksforgeeks.org/find-excel-column-name-given-number/
// Function to print Excel column name for a given column number
std::string stdString;
char str[1000]; // To store result (Excel column name)
int i = 0; // To store current index in str which is result
while ( n > 0 )
{
// Find remainder
int rem = n % 26;
// If remainder is 0, then a 'Z' must be there in output
if ( rem == 0 )
{
str[i++] = 'Z';
n = (n/26) - 1;
}
else // If remainder is non-zero
{
str[i++] = (rem-1) + 'A';
n = n / 26;
}
}
str[i] = '\0';
// Reverse the string and print result
std::reverse( str, str + strlen(str) );
stdString = str;
return stdString;
}

View File

@ -1,46 +0,0 @@
// CopycatTableModel.h
// QXlsx // MIT License // https://github.com/j2doll/QXlsx
#ifndef XLSX_MODEL_H
#define XLSX_MODEL_H
#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#include <sstream>
#include <QtGlobal>
#include <QObject>
#include <QString>
#include <QStringList>
#include <QList>
#include <QVector>
#include <QMap>
#include <QVariant>
#include <QAbstractTableModel>
typedef QList<QVariant> VLIST;
class CopycatTableModel : public QAbstractTableModel
{
Q_OBJECT
public: // constrcutor
CopycatTableModel(QList<QString> colTitle, QList<VLIST> data, QObject *parent = NULL);
public: // virtual function of parent object
int rowCount(const QModelIndex & parent = QModelIndex()) const Q_DECL_OVERRIDE;
int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
protected:
QList<VLIST> m_the_data; // table cell data
QList<QString> m_colNames; // column name
quint32 m_roleCount; // role count (same as column count)
std::string convertFromNumberToExcelColumn(int n);
};
#endif

View File

@ -1,363 +0,0 @@
// MainWindow.cpp
#include <QtGlobal>
#include <QString>
#include <QFileDialog>
#include <QMessageBox>
#include <QVBoxLayout>
#include <QPrinter>
#include <QPrintPreviewDialog>
#include <QPainter>
#include <QDebug>
#include <QVector>
#include <QList>
#include <QSharedPointer>
#include <QInputDialog>
#include <QStringList>
#include <QVarLengthArray>
#include "xlsxcelllocation.h"
#include "xlsxcell.h"
#include "CopycatTableModel.h"
#include "tableprinter.h"
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
xlsxDoc = NULL;
tabWidget = NULL;
ui->setupUi(this);
tabWidget = new QTabWidget(this);
setCentralWidget(tabWidget);
this->setWindowTitle(QString("Copycat"));
setWindowIcon(QIcon(":/excel.ico"));
}
MainWindow::~MainWindow()
{
delete ui;
if ( NULL != xlsxDoc )
{
delete xlsxDoc;
}
}
void MainWindow::on_action_Quit_triggered()
{
// quit
this->close();
}
void MainWindow::on_action_Open_triggered()
{
// open file dialog
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Excel"), ".", tr("Excel Files (*.xlsx)"));
if ( ! loadXlsx(fileName) ) // load xlsx
{
QMessageBox msgBox;
QString alertMsg = QString("Failed to load file.\n %1").arg(fileName);
msgBox.setIcon( QMessageBox::Critical );
msgBox.setText( alertMsg );
msgBox.exec();
return;
}
this->setWindowTitle(fileName);
}
bool MainWindow::loadXlsx(QString fileName)
{
// tried to load xlsx using temporary document
QXlsx::Document xlsxTmp( fileName );
if ( !xlsxTmp.isLoadPackage() )
{
return false; // failed to load
}
// clear xlsxDoc
if ( NULL != xlsxDoc )
{
delete xlsxDoc;
xlsxDoc = NULL;
}
// load new xlsx using new document
xlsxDoc = new QXlsx::Document( fileName );
xlsxDoc->isLoadPackage();
// clear tab widget
tabWidget->clear();
// Removes all the pages, but does not delete them.
// Calling this function is equivalent to calling removeTab()
// until the tab widget is empty.
// clear sub-items of every tab
foreach ( XlsxTab* ptrTab, xlsxTabList )
{
if ( NULL == ptrTab )
continue;
delete ptrTab;
}
xlsxTabList.clear();
int sheetIndexNumber = 0;
int activeSheetNumber = -1;
AbstractSheet* activeSheet = xlsxDoc->workbook()->activeSheet();
// NOTICE: active sheet is lastest sheet. It's not focused sheet.
foreach( QString curretnSheetName, xlsxDoc->sheetNames() )
{
QXlsx::AbstractSheet* currentSheet = xlsxDoc->sheet( curretnSheetName );
if ( NULL == currentSheet )
continue;
if ( activeSheet == currentSheet )
{
// current sheet is active sheet.
activeSheetNumber = sheetIndexNumber;
}
XlsxTab* newSheet = new XlsxTab( this, xlsxDoc, currentSheet, sheetIndexNumber ); // create new tab
xlsxTabList.push_back( newSheet ); // append to xlsx pointer list
tabWidget->addTab( newSheet, curretnSheetName ); // add tab widget
sheetIndexNumber++; // increase sheet index number
}
if ( (-1) != activeSheetNumber )
tabWidget->setCurrentIndex(activeSheetNumber);
return true;
}
void MainWindow::on_action_About_triggered()
{
QString text =
"QXlsx Copycat<br />"
"<a href=\"https://github.com/QtExcel/QXlsx\">https://github.com/QtExcel/QXlsx</a><br />" ;
QMessageBox::about(this, "QXlsx", text);
}
void MainWindow::on_action_New_triggered()
{
// TODO: new document
QMessageBox msgBox;
msgBox.setText( "TODO: New xlsx" );
msgBox.exec();
}
void MainWindow::on_action_Save_triggered()
{
// TODO: save document
QMessageBox msgBox;
msgBox.setText( "TODO: Save xlsx" );
msgBox.exec();
}
void MainWindow::on_action_Print_triggered()
{
if ( NULL == xlsxDoc )
return;
QPrintPreviewDialog dialog;
connect(&dialog, SIGNAL(paintRequested(QPrinter*)), this, SLOT(print(QPrinter*)));
dialog.exec();
}
void MainWindow::print(QPrinter *printer)
{
if ( NULL == xlsxDoc )
{
QMessageBox msgBox;
msgBox.setText( "xlsx document is empty." );
msgBox.setIcon( QMessageBox::Warning );
msgBox.exec();
return;
}
Worksheet* wsheet = (Worksheet*) xlsxDoc->workbook()->activeSheet();
if ( NULL == wsheet )
{
QMessageBox msgBox;
msgBox.setText( "worksheet is set." );
msgBox.setIcon( QMessageBox::Warning );
msgBox.exec();
return;
}
QStringList items;
foreach( QString curretnSheetName, xlsxDoc->sheetNames() )
{
items << curretnSheetName;
}
bool ok = false;
QString selectedItem
= QInputDialog::getItem( this, tr("QXlsx"), tr("Select sheet:"), items, 0, false, &ok );
if (!ok)
{
QMessageBox msgBox;
msgBox.setText( "Please select printable sheet" );
msgBox.setIcon( QMessageBox::Warning );
msgBox.exec();
return;
}
int idx = 0;
foreach (const QString& varList, items)
{
if ( varList == selectedItem )
{
break;
}
idx++;
}
xlsxDoc->workbook()->setActiveSheet( idx );
wsheet = (Worksheet*) xlsxDoc->workbook()->activeSheet(); // set active sheet
QList<QString> colTitle;
QList<VLIST> xlsxData;
QVector<int> printColumnStretch;
int sheetIndexNumber = 0;
int maxRow = -1;
int maxCol = -1;
QVector<CellLocation> clList = wsheet->getFullCells( &maxRow, &maxCol );
// Fixed for Visual C++, cause VC++ does not support C99.
// https://docs.microsoft.com/en-us/cpp/c-language/ansi-conformance?view=vs-2017
// QString arr[maxRow][maxCol];
QVector <QVector <QString> > arr;
for (int i = 0; i < maxRow; i++)
{
QVector<QString> tempVector;
for (int j = 0; j < maxCol; j++)
{
tempVector.push_back(QString(""));
}
arr.push_back(tempVector);
}
for ( int ic = 0; ic < clList.size(); ++ic )
{
CellLocation cl = clList.at(ic);
int row = cl.row - 1;
int col = cl.col - 1;
QSharedPointer<Cell> ptrCell = cl.cell; // cell pointer
QString strValue = ptrCell->value().toString();
arr[row][col] = strValue;
}
for (int ir = 0 ; ir < maxRow; ir++)
{
VLIST vl;
for (int ic = 0 ; ic < maxCol; ic++)
{
QString strValue = arr[ir][ic];
if ( strValue.isNull() )
strValue = QString("");
vl.append( strValue );
}
xlsxData.append( vl );
}
QVector<QString> printHeaders;
for ( int ic = 0 ; ic < maxCol; ic++ )
{
std::string colString = convertFromNumberToExcelColumn( ( ic + 1 ) );
QString strCol = QString::fromStdString( colString );
colTitle.append( strCol );
printHeaders.append( strCol );
printColumnStretch.append( wsheet->columnWidth( (ic + 1) ) ); // TODO: check this code
}
CopycatTableModel copycatTableModel(colTitle, xlsxData); // model
QPainter painter;
if ( !painter.begin(printer) )
{
QMessageBox msgBox;
msgBox.setText( "Can't start printer" );
msgBox.setIcon( QMessageBox::Critical );
msgBox.exec();
return;
}
// print table
TablePrinter tablePrinter(&painter, printer);
if ( !tablePrinter.printTable( &copycatTableModel, printColumnStretch, printHeaders ) )
{
QMessageBox msgBox;
msgBox.setText( tablePrinter.lastError() );
msgBox.setIcon( QMessageBox::Warning );
msgBox.exec();
return;
}
// tablePrinter.setCellMargin( l, r, t, b );
// tablePrinter.setPageMargin( l, r, t, b );
painter.end();
}
std::string MainWindow::convertFromNumberToExcelColumn(int n)
{
// main code from https://www.geeksforgeeks.org/find-excel-column-name-given-number/
// Function to print Excel column name for a given column number
std::string stdString;
char str[1000]; // To store result (Excel column name)
int i = 0; // To store current index in str which is result
while ( n > 0 )
{
// Find remainder
int rem = n % 26;
// If remainder is 0, then a 'Z' must be there in output
if ( rem == 0 )
{
str[i++] = 'Z';
n = (n/26) - 1;
}
else // If remainder is non-zero
{
str[i++] = (rem-1) + 'A';
n = n / 26;
}
}
str[i] = '\0';
// Reverse the string and print result
std::reverse( str, str + strlen(str) );
stdString = str;
return stdString;
}

View File

@ -1,50 +0,0 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGlobal>
#include <QObject>
#include <QString>
#include <QVector>
#include <QList>
#include <QWidget>
#include <QMainWindow>
#include <QTabWidget>
#include <QPrinter>
#include "xlsx.h"
#include "XlsxTab.h"
#include "CopycatTableModel.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_action_Quit_triggered();
void on_action_Open_triggered();
void on_action_About_triggered();
void on_action_New_triggered();
void on_action_Save_triggered();
void on_action_Print_triggered();
void print(QPrinter *printer);
protected:
Ui::MainWindow *ui;
QXlsx::Document* xlsxDoc;
QTabWidget *tabWidget;
QVector<XlsxTab*> xlsxTabList;
protected:
bool loadXlsx(QString xlsxFilename);
std::string convertFromNumberToExcelColumn(int n);
};
#endif // MAINWINDOW_H

View File

@ -1,90 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>320</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="action_New"/>
<addaction name="action_Open"/>
<addaction name="action_Save"/>
<addaction name="separator"/>
<addaction name="action_Print"/>
<addaction name="separator"/>
<addaction name="action_Quit"/>
</widget>
<widget class="QMenu" name="menu_Help">
<property name="title">
<string>&amp;Help</string>
</property>
<addaction name="action_About"/>
</widget>
<addaction name="menu_File"/>
<addaction name="menu_Help"/>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="action_New">
<property name="text">
<string>&amp;New</string>
</property>
</action>
<action name="action_Open">
<property name="text">
<string>&amp;Open</string>
</property>
</action>
<action name="action_Save">
<property name="text">
<string>&amp;Save</string>
</property>
</action>
<action name="action_Quit">
<property name="text">
<string>&amp;Quit</string>
</property>
</action>
<action name="action_About">
<property name="text">
<string>&amp;About</string>
</property>
</action>
<action name="action_Print">
<property name="text">
<string>&amp;Print</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -1,27 +0,0 @@
Copyright (c) 2016, Anton Onishchenko
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,285 +0,0 @@
/****************************************************************************
**
** Copyright (c) 2016, Anton Onishchenko
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** 1. Redistributions of source code must retain the above copyright notice, this
** list of conditions and the following disclaimer.
**
** 2. Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or other
** materials provided with the distribution.
**
** 3. Neither the name of the copyright holder nor the names of its contributors may
** be used to endorse or promote products derived from this software without
** specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/
#include "tableprinter.h"
#include <QAbstractItemModel>
#include <QPainter>
#include <QPrinter>
#include <QDebug>
TablePrinter::TablePrinter(QPainter* painter, QPrinter* printer) :
painter(painter),
printer(printer)
{
topMargin = 5;
bottomMargin = 5;
leftMargin = 10;
rightMargin = 5;
headerHeight = 0;
bottomHeight = 0;
leftBlank = 0;
rightBlank = 0;
maxRowHeight = 1000;
pen = painter->pen();
headersFont = painter->font();
contentFont = painter->font();
headerColor = painter->pen().color();
contentColor = painter->pen().color();
prepare = NULL;
error = "No error";
}
bool TablePrinter::printTable(const QAbstractItemModel* model, const QVector<int> columnStretch,
const QVector<QString> headers) {
//--------------------------------- error checking -------------------------------------
int columnCount = model->columnCount();
int count = columnStretch.count();
if(count != columnCount) {
error = "Different columns count in model and in columnStretch";
return false;
}
count = headers.count();
if(count != columnCount && count != 0) {
error = "Different columns count in model and in headers";
return false;
}
if(!printer->isValid()) {
error = "printer.isValid() == false";
return false;
}
if(!painter->isActive()) {
error = "painter.isActive() == false";
return false;
}
double tableWidth = painter->viewport().width() - leftBlank - rightBlank;
if(tableWidth <= 0) {
error = "wrong table width";
return false;
}
int totalStretch = 0;
for (int i = 0; i < columnStretch.count(); i++) {
if(columnStretch[i] < 0) {
error = QString("wrong column stretch, columnt: %1 stretch: %2").arg(i).arg(columnStretch[i]);
return false;
}
totalStretch += columnStretch[i];
}
if(totalStretch <= 0) {
error = QString("wrong stretch");
return false;
}
QVector<double> columnWidth;
for (int i = 0; i < columnStretch.count(); i++) {
columnWidth.append(tableWidth / totalStretch * columnStretch[i]);
}
int initValue;
headers.isEmpty() ? initValue = 0 : initValue = -1;
//----------------------------------------------------------------------------
painter->save(); // before table print
// to know row height before printing
// at first print to test image
QPainter testSize;
QImage* image = new QImage(10, 10, QImage::Format_RGB32);
image->setDotsPerMeterX(printer->logicalDpiX() * 100 / 2.54); // 2.54 cm = 1 inch
image->setDotsPerMeterY(printer->logicalDpiY() * 100 / 2.54);
testSize.begin(image);
if(prepare) {
painter->save();
painter->translate(-painter->transform().dx(), -painter->transform().dy());
prepare->preparePage(painter);
painter->restore();
}
painter->setPen(pen);
painter->setFont(contentFont);
testSize.setFont(contentFont);
painter->translate(-painter->transform().dx() + leftBlank, 0);
painter->save();
painter->setFont(headersFont);
testSize.setFont(headersFont);
painter->drawLine(0, 0, tableWidth, 0); // first horizontal line
float max_y;
for(int j = initValue; j < model->rowCount(); j++) { // for each row
if(j == 0) {
painter->setFont(contentFont);
testSize.setFont(contentFont);
}
// --------------------------- row height counting ----------------------------
int maxHeight = 0; // max row Height
for(int i = 0; i < columnCount; i++) { // for each column
QString str;
if(j >= 0) {
// NOTE: j is row. i is column.
str = model->data(model->index(j,i), Qt::DisplayRole).toString();
} else {
str = headers.at(i);
}
// qDebug() << "\t\t\t\t[Printer] " << " i=" << i << " j=" << j << " : " << str;
QRect rect(0, 0, columnWidth[i] - rightMargin - leftMargin, maxRowHeight);
QRect realRect;
int flags = Qt::AlignLeft | Qt::TextWordWrap;
testSize.drawText( rect, flags, str, &realRect );
if (realRect.height() > maxHeight && columnStretch[i] != 0)
{
realRect.height() > maxRowHeight ? maxHeight = maxRowHeight : maxHeight = realRect.height();
}
}
if(painter->transform().dy() + maxHeight + topMargin + bottomMargin > painter->viewport().height() -
bottomHeight) { // begin from new page
int y = painter->transform().dy();
painter->restore();
painter->save();
for(int i = 0; i < columnCount; i++) { // vertical lines
painter->drawLine(0, 0, 0,
- painter->transform().dy() + y);
painter->translate(columnWidth[i], 0);
}
painter->drawLine(0, 0, 0, - painter->transform().dy() + y); // last vertical line
painter->restore();
printer->newPage();
if(prepare) {
painter->save();
painter->translate(-painter->transform().dx(), -painter->transform().dy());
prepare->preparePage(painter);
painter->restore();
}
painter->translate(-painter->transform().dx() + leftBlank, -painter->transform().dy() + headerHeight);
painter->save();
painter->drawLine(0, 0, tableWidth,
0); // first horizontal line
}
//------------------------------ content printing -------------------------------------------
painter->save();
j >= 0 ? painter->setPen(QPen(contentColor)) : painter->setPen(QPen(headerColor));
for(int i = 0; i < columnCount; i++) { // for each column
QString str;
if(j >= 0) {
str = model->data(model->index(j,i), Qt::DisplayRole).toString();
} else {
str = headers.at(i);
}
QRect rec(leftMargin, topMargin, columnWidth[i] - rightMargin - leftMargin, maxHeight);
painter->drawText(rec, Qt::AlignLeft | Qt::TextWordWrap, str);
painter->translate(columnWidth[i], 0);
}
painter->restore();
painter->drawLine(0, maxHeight + topMargin + bottomMargin, tableWidth,
maxHeight + topMargin + bottomMargin); // last horizontal line
painter->translate(0, maxHeight + topMargin + bottomMargin);
max_y = painter->transform().dy();
}
int y = painter->transform().dy();
painter->restore();
painter->save();
for(int i = 0; i < columnCount; i++) { // vertical lines
painter->drawLine(0, 0, 0,
- painter->transform().dy() + y);
painter->translate(columnWidth[i], 0);
}
painter->drawLine(0, 0, 0, - painter->transform().dy() + y); // last vertical line
painter->restore();
testSize.end();
delete image;
painter->restore(); // before table print
painter->translate(0, max_y);
return true;
}
QString TablePrinter::lastError() {
return error;
}
void TablePrinter::setCellMargin(int left, int right, int top, int bottom) {
topMargin = top;
bottomMargin = bottom;
leftMargin = left;
rightMargin = right;
}
void TablePrinter::setPageMargin(int left, int right, int top, int bottom) {
headerHeight = top;
bottomHeight = bottom;
leftBlank = left;
rightBlank = right;
}
void TablePrinter::setPagePrepare(PagePrepare *prep) {
prepare = prep;
}
void TablePrinter::setPen(QPen p) {
pen = p;
}
void TablePrinter::setHeadersFont(QFont f) {
headersFont = f;
}
void TablePrinter::setContentFont(QFont f) {
contentFont = f;
}
void TablePrinter::setHeaderColor(QColor color) {
headerColor = color;
}
void TablePrinter::setContentColor(QColor color) {
contentColor = color;
}
void TablePrinter::setMaxRowHeight(int height) {
maxRowHeight = height;
}

View File

@ -1,97 +0,0 @@
/****************************************************************************
**
** Copyright (c) 2016, Anton Onishchenko
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** 1. Redistributions of source code must retain the above copyright notice, this
** list of conditions and the following disclaimer.
**
** 2. Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or other
** materials provided with the distribution.
**
** 3. Neither the name of the copyright holder nor the names of its contributors may
** be used to endorse or promote products derived from this software without
** specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/
#ifndef TABLEPRINTER_H
#define TABLEPRINTER_H
#include <QPen>
#include <QFont>
class QPrinter;
class QPainter;
class QAbstractItemModel;
/**
* @brief The PagePrepare Abstract class - base class for
* classes that will print something like headers, borders...
* on each page with table
*/
class PagePrepare {
public:
virtual void preparePage(QPainter *painter) = 0;
virtual ~PagePrepare() {}
};
class TablePrinter
{
public:
TablePrinter(QPainter *painter, QPrinter *printer);
bool printTable(const QAbstractItemModel* model, const QVector<int> columnStretch,
const QVector<QString> headers = QVector<QString>());
QString lastError();
void setCellMargin(int left = 10, int right = 5, int top = 5, int bottom = 5);
void setPageMargin(int left = 50, int right = 20, int top = 20, int bottom = 20);
void setPagePrepare(PagePrepare *prepare);
void setPen(QPen pen); // for table borders
void setHeadersFont(QFont font);
void setContentFont(QFont font);
void setHeaderColor(QColor color);
void setContentColor(QColor color);
void setMaxRowHeight(int height);
private:
QPainter *painter;
QPrinter *printer;
PagePrepare *prepare;
QPen pen; // for table borders
QFont headersFont;
QFont contentFont;
QColor headerColor;
QColor contentColor;
// cell margins
int topMargin;
int bottomMargin;
int leftMargin;
int rightMargin;
// margins for table
int headerHeight;
int bottomHeight;
int leftBlank;
int rightBlank;
int maxRowHeight;
QString error;
};
#endif // TABLEPRINTER_H

View File

@ -1,378 +0,0 @@
// XlsxTab.cpp
#include <QtGlobal>
#include <QObject>
#include <QString>
#include <QSharedPointer>
#include <QLayout>
#include <QVBoxLayout>
#include <QVariant>
#include <QFont>
#include <QBrush>
#include <QDebug>
#include <QTextCharFormat>
#include "XlsxTab.h"
#include "xlsxcell.h"
#include "xlsxformat.h"
XlsxTab::XlsxTab(QWidget* parent,
QXlsx::Document* ptrDoc,
QXlsx::AbstractSheet* ptrSheet,
int SheetIndex)
: QWidget(parent)
{
table = NULL;
sheet = NULL;
sheetIndex = -1;
if ( NULL == ptrSheet )
return;
table = new XlsxTableWidget( this );
Q_ASSERT( NULL != table );
// set layout
vLayout = new QVBoxLayout;
vLayout->addWidget(table);
this->setLayout(vLayout);
document = ptrDoc; // set document
sheet = ptrSheet; // set sheet data
sheetIndex = SheetIndex; // set shett index
if ( ! setSheet() )
{
}
}
XlsxTab::~XlsxTab()
{
if ( NULL != vLayout )
{
vLayout->deleteLater();
vLayout = NULL;
}
if ( NULL != table )
{
table->clear();
table->deleteLater();
table = NULL;
}
}
bool XlsxTab::setSheet()
{
if ( NULL == sheet )
return false;
if ( NULL == table )
return false;
// set active sheet
sheet->workbook()->setActiveSheet( sheetIndex );
// dev57
if ( sheet->workbook()->activeSheet()->sheetType() != AbstractSheet::ST_WorkSheet )
return false;
Worksheet* wsheet = (Worksheet*) sheet->workbook()->activeSheet();
if ( NULL == wsheet )
return false;
// get full cells of sheet
int maxRow = -1;
int maxCol = -1;
QVector<CellLocation> clList = wsheet->getFullCells( &maxRow, &maxCol );
// set max count of row,col
// NOTE: This part should be modified later.
// The maximum value of the sheet should be set to an appropriate value.
table->setRowCount( maxRow );
table->setColumnCount( maxCol );
for ( int ic = 0; ic < clList.size(); ++ic )
{
// cell location
CellLocation cl = clList.at(ic);
////////////////////////////////////////////////////////////////////
/// NOTE: First cell index of tableWidget is 0(zero).
/// But, first cell of Qxlsx document is 1(one).
int row = cl.row - 1;
int col = cl.col - 1;
////////////////////////////////////////////////////////////////////
/// cell pointer
QSharedPointer<Cell> ptrCell = cl.cell;
////////////////////////////////////////////////////////////////////
/// create new item of table widget
QTableWidgetItem* newItem = new QTableWidgetItem();
///////////////////////////////////////////////////////////////////
/// value of cell
QVariant var = cl.cell.data()->value(); // cell value
QString str;
Cell::CellType cType = cl.cell->cellType();
// qDebug() << "(r,c) = " << cl.row << cl.col << var.toString() ;
str = var.toString();
////////////////////////////////////////////////////////////////////
/// set text
newItem->setText( str );
////////////////////////////////////////////////////////////////////
/// set item
table->setItem( row, col, newItem );
// TODO: set label of table widget ('A', 'B', 'C', ...)
// QTableWidgetItem *QTableWidget::horizontalHeaderItem(int column) const
// QTableWidgetItem *QTableWidget::verticalHeaderItem(int row) const
////////////////////////////////////////////////////////////////////
/// row height and column width
double dRowHeight = wsheet->rowHeight( cl.row );
double dColWidth = wsheet->columnWidth( cl.col );
// qDebug() <<" ROW HEIGHT: " << dRowHeight << " COLUMN WIDTH: " << dColWidth;
double wWidth = cellWidthToWidgetWidth( dColWidth );
double wHeight = cellHeightToWidgetHeight( dRowHeight );
table->setRowHeight( row, wHeight );
table->setColumnWidth( col, wWidth );
////////////////////////////////////////////////////////////////////
/// font
newItem->setFont( ptrCell->format().font() );
////////////////////////////////////////////////////////////////////
/// font color
if ( ptrCell->format().fontColor().isValid() )
{
newItem->setTextColor( ptrCell->format().fontColor() );
}
////////////////////////////////////////////////////////////////////
/// background color
{
QColor clrForeGround = ptrCell->format().patternForegroundColor();
if ( clrForeGround.isValid() )
{
// qDebug() << "[debug] ForeGround : " << clrForeGround;
}
QColor clrBackGround = ptrCell->format().patternBackgroundColor();
if ( clrBackGround.isValid() )
{
// TODO: You must use various patterns.
newItem->setBackground( Qt::SolidPattern );
newItem->setBackgroundColor( clrBackGround );
}
}
////////////////////////////////////////////////////////////////////
/// pattern
Format::FillPattern fp = ptrCell->format().fillPattern();
Qt::BrushStyle qbs = Qt::NoBrush;
switch(fp)
{
case Format::PatternNone : qbs = Qt::NoBrush; break;
case Format::PatternSolid : qbs = Qt::SolidPattern; break;
case Format::PatternMediumGray :
case Format::PatternDarkGray :
case Format::PatternLightGray :
case Format::PatternDarkHorizontal :
case Format::PatternDarkVertical :
case Format::PatternDarkDown :
case Format::PatternDarkUp :
case Format::PatternDarkGrid :
case Format::PatternDarkTrellis :
case Format::PatternLightHorizontal :
case Format::PatternLightVertical :
case Format::PatternLightDown :
case Format::PatternLightUp :
case Format::PatternLightTrellis :
case Format::PatternGray125 :
case Format::PatternGray0625 :
case Format::PatternLightGrid :
default:
break;
}
/*
QBrush qbr( ptrCell->format().patternForegroundColor(), qbs );
newItem->setBackground( qbr );
newItem->setBackgroundColor( ptrCell->format().patternBackgroundColor() );
*/
////////////////////////////////////////////////////////////////////
/// alignment
int alignment = 0;
Format::HorizontalAlignment ha = ptrCell->format().horizontalAlignment();
switch(ha)
{
case Format::AlignHCenter :
case Format::AlignHFill :
case Format::AlignHMerge :
case Format::AlignHDistributed :
alignment = alignment | Qt::AlignHCenter;
break;
case Format::AlignRight :
alignment = alignment | Qt::AlignRight;
break;
case Format::AlignHJustify :
alignment = alignment | Qt::AlignJustify;
break;
case Format::AlignLeft :
case Format::AlignHGeneral :
default:
alignment = alignment | Qt::AlignLeft;
break;
}
Format::VerticalAlignment va = ptrCell->format().verticalAlignment();
switch(va)
{
case Format::AlignTop :
alignment = alignment | Qt::AlignTop;
break;
case Format::AlignVCenter :
alignment = alignment | Qt::AlignVCenter;
break;
case Format::AlignBottom :
alignment = alignment | Qt::AlignBottom;
break;
case Format::AlignVJustify :
case Format::AlignVDistributed :
default:
// alignment = alignment | (int)(Qt::AlignBaseline);
alignment = alignment | QTextCharFormat::AlignBaseline;
break;
}
newItem->setTextAlignment( alignment );
////////////////////////////////////////////////////////////////////
}
// dev56
////////////////////////////////////////////////////////////////////
/// merged cell
if ( sheet->workbook()->activeSheet()->sheetType() == AbstractSheet::ST_WorkSheet )
{
QList<CellRange> mergeCellRangeList = wsheet->mergedCells();
for ( int mc = 0; mc < mergeCellRangeList.size(); ++mc )
{
CellRange mergedCellRange = mergeCellRangeList.at(mc);
CellReference crTopLeft = mergedCellRange.topLeft();
int tlCol = crTopLeft.column();
int tlRow = crTopLeft.row();
CellReference crBottomRight = mergedCellRange.bottomRight();
int brCol = crBottomRight.column();
int brRow = crBottomRight.row();
// row : tlRow ~ brRow
// col : tlCol ~ brCol
/// NOTE: First cell index of tableWidget is 0(zero).
/// But, first cell of Qxlsx document is 1(one).
int rowSpan = brRow - tlRow + 1;
int colSpan = brCol - tlCol + 1;
table->setSpan( (tlRow - 1), (tlCol - 1), rowSpan, colSpan );
} // for ( int mc = 0; mc < mergeCellRangeList.size(); ++mc ) ...
} // if ( sheet->workbook()->activeSheet()->sheetType() == AbstractSheet::ST_WorkSheet ) ...
return true;
}
std::string XlsxTab::convertFromNumberToExcelColumn(int n)
{
// main code from https://www.geeksforgeeks.org/find-excel-column-name-given-number/
// Function to print Excel column name for a given column number
std::string stdString;
char str[1000]; // To store result (Excel column name)
int i = 0; // To store current index in str which is result
while ( n > 0 )
{
// Find remainder
int rem = n % 26;
// If remainder is 0, then a 'Z' must be there in output
if ( rem == 0 )
{
str[i++] = 'Z';
n = (n/26) - 1;
}
else // If remainder is non-zero
{
str[i++] = (rem-1) + 'A';
n = n / 26;
}
}
str[i] = '\0';
// Reverse the string and print result
std::reverse( str, str + strlen(str) );
stdString = str;
return stdString;
}
// 72 points (DPI) = 1 inch = 2.54 cm = 96 pixels
// 1 PT(point) = 1.333 PX(pixel) (point is a absolute unit.)
// 1 PX(pixel) = 0.75 PT(point) (pixel is a relative unit.) (In Windows. Mac is diffrent.)
double XlsxTab::cellWidthToWidgetWidth(double width)
{
// unit of width is a character. default value is 8.43.
// 8.43 characters = 64 pixel = 48 point (in Windows)
double ret = width * (double(64) / double(8.43));
return ret;
}
double XlsxTab::cellHeightToWidgetHeight(double height)
{
// default value is 16.5 point
// 3 point = 4 pixel
double ret = height * (double(3) / double(4));
return ret;
}

View File

@ -1,53 +0,0 @@
// XlsxTab.h
#ifndef XLSXTAB_H
#define XLSXTAB_H
#include <cstdio>
#include <string>
#include <QtGlobal>
#include <QObject>
#include <QString>
#include <QWidget>
#include <QTableWidget>
#include <QVBoxLayout>
#include "xlsx.h"
#include "XlsxTableWidget.h"
/**
* @brief xlsx sub-tab widget
*/
class XlsxTab : public QWidget
{
Q_OBJECT
public:
explicit XlsxTab(QWidget* parent = NULL,
QXlsx::Document* ptrDoc = NULL,
QXlsx::AbstractSheet* ptrSheet = NULL,
int SheetIndex = -1);
virtual ~XlsxTab();
public slots:
signals:
protected:
QXlsx::Document* document;
QXlsx::AbstractSheet* sheet;
int sheetIndex;
protected:
XlsxTableWidget* table;
QVBoxLayout *vLayout;
protected:
bool setSheet();
std::string convertFromNumberToExcelColumn(int n);
double cellWidthToWidgetWidth(double width);
double cellHeightToWidgetHeight(double height);
};
#endif // XLSXTAB_H

View File

@ -1,66 +0,0 @@
// XlsxTableWidget.cpp
#include <QDebug>
#include <QTime>
#include <QList>
#include <QTableWidgetSelectionRange>
#include "XlsxTableWidget.h"
XlsxTableWidget::XlsxTableWidget(QWidget* parent)
: QTableWidget(parent)
{
//
}
XlsxTableWidget::~XlsxTableWidget()
{
}
void XlsxTableWidget::mousePressEvent(QMouseEvent *event)
{
QTableWidget::mousePressEvent(event);
if ( event->button() == Qt::RightButton )
{
// qDebug() << "right button is pressed";
QList<QTableWidgetItem *> items = this->selectedItems();
// selected range
QList<QTableWidgetSelectionRange> ranges = this->selectedRanges();
for (int ic = 0 ; ic < ranges.size(); ic++ )
{
QTableWidgetSelectionRange range = ranges.at(ic);
int rowCount = range.rowCount();
int topRow = range.topRow();
int bottomRow = range.bottomRow();
int colCount = range.columnCount();
int leftCol = range.leftColumn();
int rightCol = range.rightColumn();
// qDebug()
// << QTime::currentTime();
// qDebug()
// << "row: " << rowCount << " : "
// << " top:" << topRow
// << ", bottom:" << bottomRow ;
// qDebug()
// << "col: " << colCount << " : "
// << " left:" << leftCol
// << " right:" << rightCol ;
}
}
}

View File

@ -1,30 +0,0 @@
// XlsxTableWidget.h
#ifndef XLSX_TABLE_WIDGET_H
#define XLSX_TABLE_WIDGET_H
#include <cstdio>
#include <QtGlobal>
#include <QList>
#include <QVector>
#include <QWidget>
#include <QTableWidget>
#include <QMouseEvent>
#include <QTableWidgetItem>
#include <QTableWidgetSelectionRange>
class XlsxTableWidget : public QTableWidget
{
Q_OBJECT
public:
explicit XlsxTableWidget(QWidget* parent = NULL);
virtual ~XlsxTableWidget();
protected:
virtual void mousePressEvent(QMouseEvent *event);
};
#endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

View File

@ -1,17 +0,0 @@
// main.cpp
#include <QtGlobal>
#include "MainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
int ret = a.exec();
return ret;
}

View File

@ -1,5 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>excel.ico</file>
</qresource>
</RCC>

Binary file not shown.

Binary file not shown.

View File

@ -1,14 +0,0 @@
#ifndef XLSX_H
#define XLSX_H
#include "xlsxdocument.h"
#include "xlsxchartsheet.h"
#include "xlsxcellrange.h"
#include "xlsxchart.h"
#include "xlsxrichstring.h"
#include "xlsxworkbook.h"
#include "xlsxabstractsheet.h"
using namespace QXlsx;
#endif // XLSX_H

View File

@ -83,14 +83,6 @@ int main(int argc, char *argv[])
![](markdown.data/android.jpg)
## [Copycat : Windows Widget Example](https://github.com/QtExcel/QXlsx/tree/master/Copycat)
- Load xlsx file and display on Qt widgets.
- Print xlsx to paper. (based on Qt-Table-Printer)
- TODO: save xlsx.
![](markdown.data/copycat.png)
![](markdown.data/copycat2.jpg)
## [WebServer : Web Server Example](https://github.com/QtExcel/QXlsx/tree/master/WebServer)
- Load xlsx file and display on Web.
- Connect to `http://127.0.0.1:3001`
@ -104,3 +96,11 @@ int main(int argc, char *argv[])
- C++ 11 is required. Old compilers is not supported. (based on libfort)
![](markdown.data/show-console.jpg)
## Copycat : Windows Widget Example
- Load xlsx file and display on Qt widgets.
- Print xlsx to paper. (based on Qt-Table-Printer)
- Moved to personal repository for advanced app.
![](markdown.data/copycat.png)
![](markdown.data/copycat2.jpg)

View File

@ -14,7 +14,6 @@
- HelloWorld : 헬로우 월드 예제 (가장 기본적인 구조)
- TestExcel : QtXlsx 예제에 기반한 기본 예제
- HelloAndroid : 안드로이드에서 xlsx 파일 열기
- Copycat : xlsx 파일을 읽어 위젯으로 표시. xlsx 파일 인쇄.
- WebServer : xlsx 파일을 읽어 웹으로 표시
- ShowConsole : xlsx 파일을 읽어 콘솔에 표시

View File

@ -14,7 +14,6 @@
- HelloWorld : Hello world example (the most basic structure)
- TestExcel : basic samples based on QtXlsx samples
- HelloAndroid : read xlsx on Android
- Copycat : load xlsx file and display on widget. print xlsx file.
- WebServer : load xlsx and display to web
- ShowConsole : load xlsx and display to console