增加旋转实时显示
This commit is contained in:
parent
76ba7bc5e5
commit
3e8474ea5a
|
@ -255,4 +255,4 @@ TRANSLATIONS += \
|
|||
ts/app_ja.ts \
|
||||
ts/app_pt.ts
|
||||
|
||||
include(./xlsx/qtxlsx.pri)
|
||||
include(./QXlsx/QXlsx.pri)
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
# CMakeLists.txt for QXlsx Library
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(QXlsx
|
||||
VERSION 1.5.0
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(NOT DEFINED QT_VERSION_MAJOR)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui REQUIRED)
|
||||
endif()
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui REQUIRED)
|
||||
|
||||
if(Qt6Gui_VERSION VERSION_GREATER_EQUAL "6.10.0")
|
||||
find_package(Qt6 REQUIRED COMPONENTS GuiPrivate)
|
||||
endif()
|
||||
|
||||
set(EXPORT_NAME QXlsxQt${QT_VERSION_MAJOR})
|
||||
|
||||
if (QT_VERSION_MAJOR EQUAL 6)
|
||||
set(CMAKE_CXX_STANDARD 17 CACHE STRING "")
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 11 CACHE STRING "")
|
||||
endif()
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
||||
|
||||
if(NOT DEFINED QXLSX_PARENTPATH)
|
||||
set(QXLSX_PARENTPATH ${CMAKE_CURRENT_SOURCE_DIR}/../)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED QXLSX_HEADERPATH)
|
||||
set(QXLSX_HEADERPATH ${CMAKE_CURRENT_SOURCE_DIR}/../QXlsx/header/)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED QXLSX_SOURCEPATH)
|
||||
set(QXLSX_SOURCEPATH ${CMAKE_CURRENT_SOURCE_DIR}/../QXlsx/source/)
|
||||
endif()
|
||||
|
||||
# Due historical reasons this value is kept off
|
||||
option(BUILD_SHARED_LIBS "Build in shared lib mode" OFF)
|
||||
|
||||
set(SRC_FILES
|
||||
source/xlsxcellrange.cpp
|
||||
source/xlsxcellrange.cpp
|
||||
source/xlsxcontenttypes.cpp
|
||||
source/xlsxdrawinganchor.cpp
|
||||
source/xlsxrichstring.cpp
|
||||
source/xlsxworkbook.cpp
|
||||
source/xlsxabstractooxmlfile.cpp
|
||||
source/xlsxcellreference.cpp
|
||||
source/xlsxdatavalidation.cpp
|
||||
source/xlsxdrawing.cpp
|
||||
source/xlsxsharedstrings.cpp
|
||||
source/xlsxworksheet.cpp
|
||||
source/xlsxabstractsheet.cpp
|
||||
source/xlsxchart.cpp
|
||||
source/xlsxdatetype.cpp
|
||||
source/xlsxformat.cpp
|
||||
source/xlsxsimpleooxmlfile.cpp
|
||||
source/xlsxzipreader.cpp
|
||||
source/xlsxcell.cpp
|
||||
source/xlsxchartsheet.cpp
|
||||
source/xlsxdocpropsapp.cpp
|
||||
source/xlsxmediafile.cpp
|
||||
source/xlsxstyles.cpp
|
||||
source/xlsxzipwriter.cpp
|
||||
source/xlsxcellformula.cpp
|
||||
source/xlsxcolor.cpp
|
||||
source/xlsxdocpropscore.cpp
|
||||
source/xlsxnumformatparser.cpp
|
||||
source/xlsxtheme.cpp
|
||||
source/xlsxcelllocation.cpp
|
||||
source/xlsxconditionalformatting.cpp
|
||||
source/xlsxdocument.cpp
|
||||
source/xlsxrelationships.cpp
|
||||
source/xlsxutility.cpp
|
||||
header/xlsxabstractooxmlfile_p.h
|
||||
header/xlsxchartsheet_p.h
|
||||
header/xlsxdocpropsapp_p.h
|
||||
header/xlsxformat_p.h
|
||||
header/xlsxsharedstrings_p.h
|
||||
header/xlsxworkbook_p.h
|
||||
header/xlsxabstractsheet_p.h
|
||||
header/xlsxcolor_p.h
|
||||
header/xlsxdocpropscore_p.h
|
||||
header/xlsxmediafile_p.h
|
||||
header/xlsxsimpleooxmlfile_p.h
|
||||
header/xlsxworksheet_p.h
|
||||
header/xlsxcellformula_p.h
|
||||
header/xlsxconditionalformatting_p.h
|
||||
header/xlsxdocument_p.h
|
||||
header/xlsxnumformatparser_p.h
|
||||
header/xlsxstyles_p.h
|
||||
header/xlsxzipreader_p.h
|
||||
header/xlsxcell_p.h
|
||||
header/xlsxcontenttypes_p.h
|
||||
header/xlsxdrawinganchor_p.h
|
||||
header/xlsxrelationships_p.h
|
||||
header/xlsxtheme_p.h
|
||||
header/xlsxzipwriter_p.h
|
||||
header/xlsxchart_p.h
|
||||
header/xlsxdatavalidation_p.h
|
||||
header/xlsxdrawing_p.h
|
||||
header/xlsxrichstring_p.h
|
||||
header/xlsxutility_p.h
|
||||
)
|
||||
|
||||
set(QXLSX_PUBLIC_HEADERS
|
||||
header/xlsxabstractooxmlfile.h
|
||||
header/xlsxabstractsheet.h
|
||||
header/xlsxabstractsheet_p.h
|
||||
header/xlsxcellformula.h
|
||||
header/xlsxcell.h
|
||||
header/xlsxcelllocation.h
|
||||
header/xlsxcellrange.h
|
||||
header/xlsxcellreference.h
|
||||
header/xlsxchart.h
|
||||
header/xlsxchartsheet.h
|
||||
header/xlsxconditionalformatting.h
|
||||
header/xlsxdatavalidation.h
|
||||
header/xlsxdatetype.h
|
||||
header/xlsxdocument.h
|
||||
header/xlsxformat.h
|
||||
header/xlsxglobal.h
|
||||
header/xlsxrichstring.h
|
||||
header/xlsxworkbook.h
|
||||
header/xlsxworksheet.h
|
||||
)
|
||||
|
||||
add_library(QXlsx
|
||||
${SRC_FILES}
|
||||
${QXLSX_PUBLIC_HEADERS}
|
||||
)
|
||||
|
||||
add_library(QXlsx::QXlsx ALIAS QXlsx)
|
||||
|
||||
target_compile_definitions(QXlsx PRIVATE
|
||||
QT_NO_KEYWORDS
|
||||
QT_NO_CAST_TO_ASCII
|
||||
QT_NO_CAST_FROM_ASCII
|
||||
QT_NO_URL_CAST_FROM_STRING
|
||||
QT_NO_CAST_FROM_BYTEARRAY
|
||||
QT_USE_QSTRINGBUILDER
|
||||
QT_NO_SIGNALS_SLOTS_KEYWORDS
|
||||
QT_USE_FAST_OPERATOR_PLUS
|
||||
QT_DISABLE_DEPRECATED_BEFORE=0x060600
|
||||
)
|
||||
|
||||
if (NOT WIN32)
|
||||
# Strict iterators can't be used on Windows, they lead to a link error
|
||||
# when application code iterates over a QVector<QPoint> for instance, unless
|
||||
# Qt itself was also built with strict iterators.
|
||||
# See example at https://bugreports.qt.io/browse/AUTOSUITE-946
|
||||
target_compile_definitions(QXlsx PRIVATE QT_STRICT_ITERATORS)
|
||||
endif()
|
||||
|
||||
target_compile_features(QXlsx INTERFACE cxx_std_11)
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(QXlsx PUBLIC QXlsx_SHAREDLIB)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::GuiPrivate
|
||||
)
|
||||
|
||||
target_include_directories(QXlsx
|
||||
PRIVATE
|
||||
${QXLSX_HEADERPATH}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/header>
|
||||
$<INSTALL_INTERFACE:include/QXlsxQt${QT_VERSION_MAJOR}>
|
||||
)
|
||||
|
||||
set_target_properties(QXlsx PROPERTIES
|
||||
OUTPUT_NAME ${EXPORT_NAME}
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
PUBLIC_HEADER "${QXLSX_PUBLIC_HEADERS}"
|
||||
)
|
||||
|
||||
install(TARGETS QXlsx
|
||||
EXPORT ${EXPORT_NAME}Targets DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/QXlsxQt${QT_VERSION_MAJOR} COMPONENT devel
|
||||
)
|
||||
|
||||
install(EXPORT ${EXPORT_NAME}Targets
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${EXPORT_NAME}/
|
||||
FILE ${EXPORT_NAME}Targets.cmake
|
||||
NAMESPACE QXlsx::
|
||||
COMPONENT devel
|
||||
)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/qxlsx-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${EXPORT_NAME}Config.cmake
|
||||
@ONLY
|
||||
)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/qxlsx-config-version.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${EXPORT_NAME}ConfigVersion.cmake
|
||||
@ONLY
|
||||
)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${EXPORT_NAME}Config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${EXPORT_NAME}ConfigVersion.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${EXPORT_NAME}/
|
||||
)
|
||||
include(CPackConfig)
|
|
@ -0,0 +1,204 @@
|
|||
########################################
|
||||
# QXlsx.pri
|
||||
########################################
|
||||
|
||||
QT += core
|
||||
QT += gui-private
|
||||
|
||||
# TODO: Define your C++ version. c++14, c++17, etc.
|
||||
CONFIG += c++11
|
||||
|
||||
# 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
|
||||
|
||||
# For DLL visibility
|
||||
#DEFINES += QXlsx_SHAREDLIB QXlsx_EXPORTS
|
||||
|
||||
# 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
|
||||
|
||||
isEmpty(QXLSX_PARENTPATH) {
|
||||
message( 'QXLSX_PARENTPATH is empty. use default value.' )
|
||||
QXLSX_PARENTPATH = $$PWD/../
|
||||
} else {
|
||||
message( 'QXLSX_PARENTPATH is not empty.' )
|
||||
message( $${QXLSX_PARENTPATH} )
|
||||
}
|
||||
|
||||
isEmpty(QXLSX_HEADERPATH) {
|
||||
message( 'QXLSX_HEADERPATH is empty. use default value.' )
|
||||
QXLSX_HEADERPATH = $$PWD/../QXlsx/header/
|
||||
} else {
|
||||
message( 'QXLSX_HEADERPATH is not empty.' )
|
||||
message( $${QXLSX_HEADERPATH} )
|
||||
}
|
||||
|
||||
isEmpty(QXLSX_SOURCEPATH) {
|
||||
message( 'QXLSX_SOURCEPATH is empty. use default value.' )
|
||||
QXLSX_SOURCEPATH = $$PWD/../QXlsx/source/
|
||||
} else {
|
||||
message( 'QXLSX_SOURCEPATH is not empty.' )
|
||||
message( $${QXLSX_SOURCEPATH} )
|
||||
}
|
||||
|
||||
INCLUDEPATH += $$PWD
|
||||
INCLUDEPATH += $${QXLSX_PARENTPATH}
|
||||
INCLUDEPATH += $${QXLSX_HEADERPATH}
|
||||
|
||||
########################################
|
||||
# source code
|
||||
|
||||
HEADERS += \
|
||||
$${QXLSX_HEADERPATH}xlsxabstractooxmlfile.h \
|
||||
$${QXLSX_HEADERPATH}xlsxabstractooxmlfile_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxabstractsheet.h \
|
||||
$${QXLSX_HEADERPATH}xlsxabstractsheet_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxcell.h \
|
||||
$${QXLSX_HEADERPATH}xlsxcellformula.h \
|
||||
$${QXLSX_HEADERPATH}xlsxcellformula_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxcelllocation.h \
|
||||
$${QXLSX_HEADERPATH}xlsxcellrange.h \
|
||||
$${QXLSX_HEADERPATH}xlsxcellreference.h \
|
||||
$${QXLSX_HEADERPATH}xlsxcell_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxchart.h \
|
||||
$${QXLSX_HEADERPATH}xlsxchartsheet.h \
|
||||
$${QXLSX_HEADERPATH}xlsxchartsheet_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxchart_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxcolor_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxconditionalformatting.h \
|
||||
$${QXLSX_HEADERPATH}xlsxconditionalformatting_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxcontenttypes_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxdatavalidation.h \
|
||||
$${QXLSX_HEADERPATH}xlsxdatavalidation_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxdatetype.h \
|
||||
$${QXLSX_HEADERPATH}xlsxdocpropsapp_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxdocpropscore_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxdocument.h \
|
||||
$${QXLSX_HEADERPATH}xlsxdocument_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxdrawinganchor_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxdrawing_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxformat.h \
|
||||
$${QXLSX_HEADERPATH}xlsxformat_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxglobal.h \
|
||||
$${QXLSX_HEADERPATH}xlsxmediafile_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxnumformatparser_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxrelationships_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxrichstring.h \
|
||||
$${QXLSX_HEADERPATH}xlsxrichstring_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxsharedstrings_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxsimpleooxmlfile_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxstyles_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxtheme_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxutility_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxworkbook.h \
|
||||
$${QXLSX_HEADERPATH}xlsxworkbook_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxworksheet.h \
|
||||
$${QXLSX_HEADERPATH}xlsxworksheet_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxzipreader_p.h \
|
||||
$${QXLSX_HEADERPATH}xlsxzipwriter_p.h
|
||||
|
||||
SOURCES += \
|
||||
$${QXLSX_SOURCEPATH}xlsxabstractooxmlfile.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxabstractsheet.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxcell.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxcellformula.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxcelllocation.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxcellrange.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxcellreference.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxchart.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxchartsheet.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxcolor.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxconditionalformatting.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxcontenttypes.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxdatavalidation.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxdatetype.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxdocpropsapp.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxdocpropscore.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxdocument.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxdrawing.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxdrawinganchor.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxformat.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxmediafile.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxnumformatparser.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxrelationships.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxrichstring.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxsharedstrings.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxsimpleooxmlfile.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxstyles.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxtheme.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxutility.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxworkbook.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxworksheet.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxzipreader.cpp \
|
||||
$${QXLSX_SOURCEPATH}xlsxzipwriter.cpp
|
||||
|
||||
|
||||
########################################
|
||||
# custom setting for compiler & system
|
||||
|
||||
win32-g++ {
|
||||
message("compiling for windows g++. mingw or msys or cygwin.")
|
||||
INCLUDEPATH += $${QXLSX_HEADERPATH}win32-gcc
|
||||
CONFIG(debug, debug|release) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
win32-msvc2013 {
|
||||
message("Compiling for Visual Studio 2013")
|
||||
INCLUDEPATH += $${QXLSX_HEADERPATH}msvc2013
|
||||
CONFIG(debug, debug|release) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
win32-msvc2015 {
|
||||
message("Compiling for Visual Studio 2015")
|
||||
INCLUDEPATH += $${QXLSX_HEADERPATH}msvc2015
|
||||
CONFIG(debug, debug|release) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
win32-msvc2017 {
|
||||
message("Compiling for Visual Studio 2017")
|
||||
INCLUDEPATH += $${QXLSX_HEADERPATH}msvc2017
|
||||
CONFIG(debug, debug|release) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
win32-msvc2019 {
|
||||
message("Compiling for Visual Studio 2019")
|
||||
INCLUDEPATH += $${QXLSX_HEADERPATH}msvc2019
|
||||
CONFIG(debug, debug|release) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
unix {
|
||||
!contains(QT_ARCH, x86_64){
|
||||
LIB=lib32
|
||||
message("compiling for 32bit linux/unix system")
|
||||
} else {
|
||||
LIB=lib64
|
||||
message("compiling for 64bit linux/unix system")
|
||||
}
|
||||
|
||||
INCLUDEPATH += $${QXLSX_HEADERPATH}unix-gcc
|
||||
|
||||
# target.path = /usr/lib
|
||||
# INSTALLS += target
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
mac {
|
||||
message("compiling for mac os")
|
||||
INCLUDEPATH += $${QXLSX_HEADERPATH}mac
|
||||
CONFIG(debug, debug|release) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# QXlsx.pro
|
||||
|
||||
TARGET = QXlsx
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
QT += core
|
||||
QT += gui-private
|
||||
|
||||
#####################################################################
|
||||
# set debug/release build environment
|
||||
#
|
||||
# CONFIG += debug_and_release
|
||||
# release: DESTDIR = lib-release
|
||||
# debug: DESTDIR = lib-debug
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which as 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
|
||||
|
||||
QXLSX_PARENTPATH=$$PWD/
|
||||
QXLSX_HEADERPATH=$$PWD/header/
|
||||
QXLSX_SOURCEPATH=$$PWD/source/
|
||||
include($$PWD/QXlsx.pri)
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# SPDX-FileCopyrightText: (C) 2021 Daniel Nicoletti <dantti12@gmail.com>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
set(CPACK_PACKAGE_VENDOR "Daniel Nicoletti")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "QXlsx library.")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/../README.md")
|
||||
set(CPACK_PACKAGE_CONTACT "Daniel Nicoletti <dantti12@gmail.com>")
|
||||
|
||||
if(UNIX)
|
||||
if(NOT CPACK_GENERATOR)
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
endif()
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
set(CPACK_STRIP_FILES 1)
|
||||
if(${CMAKE_VERSION} VERSION_GREATER "3.5")
|
||||
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CPack)
|
|
@ -0,0 +1,15 @@
|
|||
# SPDX-FileCopyrightText: (C) 2021 Daniel Nicoletti <dantti12@gmail.com>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
SET(PACKAGE_VERSION @PROJECT_VERSION@)
|
||||
IF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
|
||||
SET(PACKAGE_VERSION_EXACT "true")
|
||||
ENDIF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
|
||||
IF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
|
||||
SET(PACKAGE_VERSION_COMPATIBLE "true")
|
||||
ELSE (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
|
||||
SET(PACKAGE_VERSION_UNSUITABLE "true")
|
||||
ENDIF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
|
||||
IF (PACKAGE_VERSION_UNSUITABLE)
|
||||
MESSAGE("VERSION CHECK FAILED FOR ${PACKAGE_FIND_NAME}. WANTED ${PACKAGE_FIND_VERSION}, HAVE ${PACKAGE_VERSION}")
|
||||
ENDIF(PACKAGE_VERSION_UNSUITABLE)
|
|
@ -0,0 +1,14 @@
|
|||
# SPDX-FileCopyrightText: (C) 2021 Daniel Nicoletti <dantti12@gmail.com>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# - Config information for QXlsx
|
||||
# This file defines:
|
||||
#
|
||||
# QXlsx_INCLUDE_DIR - the QXlsx include directory
|
||||
# QXlsx_LIBRARY - Link these to use QXlsx
|
||||
|
||||
SET(prefix "@CMAKE_INSTALL_PREFIX@")
|
||||
SET(exec_prefix "@CMAKE_INSTALL_PREFIX@")
|
||||
SET(QXlsx_FOUND "TRUE")
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@EXPORT_NAME@Targets.cmake")
|
|
@ -0,0 +1,43 @@
|
|||
// xlsxabstractooxmlfile.h
|
||||
|
||||
#ifndef QXLSX_XLSXABSTRACTOOXMLFILE_H
|
||||
#define QXLSX_XLSXABSTRACTOOXMLFILE_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Relationships;
|
||||
class AbstractOOXmlFilePrivate;
|
||||
|
||||
class QXLSX_EXPORT AbstractOOXmlFile
|
||||
{
|
||||
Q_DECLARE_PRIVATE(AbstractOOXmlFile)
|
||||
|
||||
public:
|
||||
enum CreateFlag { F_NewFromScratch, F_LoadFromExists };
|
||||
|
||||
public:
|
||||
virtual ~AbstractOOXmlFile();
|
||||
|
||||
virtual void saveToXmlFile(QIODevice *device) const = 0;
|
||||
virtual bool loadFromXmlFile(QIODevice *device) = 0;
|
||||
|
||||
virtual QByteArray saveToXmlData() const;
|
||||
virtual bool loadFromXmlData(const QByteArray &data);
|
||||
|
||||
Relationships *relationships() const;
|
||||
|
||||
void setFilePath(const QString path);
|
||||
QString filePath() const;
|
||||
|
||||
protected:
|
||||
AbstractOOXmlFile(CreateFlag flag);
|
||||
AbstractOOXmlFile(AbstractOOXmlFilePrivate *d);
|
||||
|
||||
AbstractOOXmlFilePrivate *d_ptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_XLSXABSTRACTOOXMLFILE_H
|
|
@ -0,0 +1,30 @@
|
|||
// xlsxabstractooxmlfile_p.h
|
||||
|
||||
#ifndef XLSXOOXMLFILE_P_H
|
||||
#define XLSXOOXMLFILE_P_H
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
#include "xlsxglobal.h"
|
||||
#include "xlsxrelationships_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class AbstractOOXmlFilePrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(AbstractOOXmlFile)
|
||||
|
||||
public:
|
||||
AbstractOOXmlFilePrivate(AbstractOOXmlFile *q, AbstractOOXmlFile::CreateFlag flag);
|
||||
virtual ~AbstractOOXmlFilePrivate();
|
||||
|
||||
public:
|
||||
QString filePathInPackage; // such as "xl/worksheets/sheet1.xml"
|
||||
|
||||
Relationships *relationships;
|
||||
AbstractOOXmlFile::CreateFlag flag;
|
||||
AbstractOOXmlFile *q_ptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXOOXMLFILE_P_H
|
|
@ -0,0 +1,49 @@
|
|||
// xlsxabstractsheet.h
|
||||
|
||||
#ifndef XLSXABSTRACTSHEET_H
|
||||
#define XLSXABSTRACTSHEET_H
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Workbook;
|
||||
class Drawing;
|
||||
class AbstractSheetPrivate;
|
||||
|
||||
class QXLSX_EXPORT AbstractSheet : public AbstractOOXmlFile
|
||||
{
|
||||
Q_DECLARE_PRIVATE(AbstractSheet)
|
||||
|
||||
public:
|
||||
Workbook *workbook() const;
|
||||
|
||||
public:
|
||||
// NOTE: If all Qt compiler supports C++1x, recommend to use a 'class enum'.
|
||||
enum SheetType { ST_WorkSheet, ST_ChartSheet, ST_DialogSheet, ST_MacroSheet };
|
||||
enum SheetState { SS_Visible, SS_Hidden, SS_VeryHidden };
|
||||
|
||||
public:
|
||||
QString sheetName() const;
|
||||
SheetType sheetType() const;
|
||||
SheetState sheetState() const;
|
||||
void setSheetState(SheetState ss);
|
||||
bool isHidden() const;
|
||||
bool isVisible() const;
|
||||
void setHidden(bool hidden);
|
||||
void setVisible(bool visible);
|
||||
|
||||
protected:
|
||||
friend class Workbook;
|
||||
AbstractSheet(const QString &sheetName, int sheetId, Workbook *book, AbstractSheetPrivate *d);
|
||||
virtual AbstractSheet *copy(const QString &distName, int distId) const = 0;
|
||||
void setSheetName(const QString &sheetName);
|
||||
void setSheetType(SheetType type);
|
||||
int sheetId() const;
|
||||
|
||||
Drawing *drawing() const;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif // XLSXABSTRACTSHEET_H
|
|
@ -0,0 +1,35 @@
|
|||
// xlsxabstractsheet_p/h
|
||||
|
||||
#ifndef XLSXABSTRACTSHEET_P_H
|
||||
#define XLSXABSTRACTSHEET_P_H
|
||||
|
||||
#include "xlsxabstractooxmlfile_p.h"
|
||||
#include "xlsxabstractsheet.h"
|
||||
#include "xlsxdrawing_p.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class AbstractSheetPrivate : public AbstractOOXmlFilePrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(AbstractSheet)
|
||||
public:
|
||||
AbstractSheetPrivate(AbstractSheet *p, AbstractSheet::CreateFlag flag);
|
||||
~AbstractSheetPrivate();
|
||||
|
||||
Workbook *workbook;
|
||||
std::shared_ptr<Drawing> drawing;
|
||||
|
||||
QString name;
|
||||
int id;
|
||||
AbstractSheet::SheetState sheetState;
|
||||
AbstractSheet::SheetType type;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXABSTRACTSHEET_P_H
|
|
@ -0,0 +1,80 @@
|
|||
// xlsxcell.h
|
||||
|
||||
#ifndef QXLSX_XLSXCELL_H
|
||||
#define QXLSX_XLSXCELL_H
|
||||
|
||||
#include "xlsxformat.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QTime>
|
||||
#include <QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Worksheet;
|
||||
class Format;
|
||||
class CellFormula;
|
||||
class CellPrivate;
|
||||
class WorksheetPrivate;
|
||||
|
||||
class QXLSX_EXPORT Cell
|
||||
{
|
||||
Q_DECLARE_PRIVATE(Cell)
|
||||
|
||||
private:
|
||||
friend class Worksheet;
|
||||
friend class WorksheetPrivate;
|
||||
|
||||
public:
|
||||
enum CellType // See ECMA 376, 18.18.11. ST_CellType (Cell Type) for more information.
|
||||
{
|
||||
BooleanType,
|
||||
DateType,
|
||||
ErrorType,
|
||||
InlineStringType,
|
||||
NumberType,
|
||||
SharedStringType,
|
||||
StringType,
|
||||
CustomType, // custom or un-defined cell type
|
||||
};
|
||||
|
||||
public:
|
||||
Cell(const QVariant &data = QVariant(),
|
||||
CellType type = NumberType,
|
||||
const Format &format = Format(),
|
||||
Worksheet *parent = nullptr,
|
||||
qint32 styleIndex = (-1));
|
||||
Cell(const Cell *const cell);
|
||||
~Cell();
|
||||
|
||||
public:
|
||||
CellPrivate *const d_ptr; // See D-pointer and Q-pointer of Qt, for more information.
|
||||
|
||||
public:
|
||||
CellType cellType() const;
|
||||
QVariant value() const;
|
||||
QVariant readValue() const;
|
||||
Format format() const;
|
||||
|
||||
bool hasFormula() const;
|
||||
CellFormula formula() const;
|
||||
|
||||
bool isDateTime() const;
|
||||
QVariant dateTime() const; // QDateTime, QDate, QTime
|
||||
|
||||
bool isRichString() const;
|
||||
|
||||
qint32 styleNumber() const;
|
||||
|
||||
static bool isDateType(CellType cellType, const Format &format);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_XLSXCELL_H
|
|
@ -0,0 +1,42 @@
|
|||
// xlsxcell_p.h
|
||||
|
||||
#ifndef XLSXCELL_P_H
|
||||
#define XLSXCELL_P_H
|
||||
|
||||
#include "xlsxcell.h"
|
||||
#include "xlsxcellformula.h"
|
||||
#include "xlsxcellrange.h"
|
||||
#include "xlsxglobal.h"
|
||||
#include "xlsxrichstring.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class CellPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(Cell)
|
||||
public:
|
||||
CellPrivate(Cell *p);
|
||||
CellPrivate(const CellPrivate *const cp);
|
||||
|
||||
public:
|
||||
Worksheet *parent;
|
||||
Cell *q_ptr;
|
||||
|
||||
public:
|
||||
Cell::CellType cellType;
|
||||
QVariant value;
|
||||
|
||||
CellFormula formula;
|
||||
Format format;
|
||||
|
||||
RichString richString;
|
||||
|
||||
qint32 styleNumber;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXCELL_P_H
|
|
@ -0,0 +1,56 @@
|
|||
// xlsxcellformula.h
|
||||
|
||||
#ifndef QXLSX_XLSXCELLFORMULA_H
|
||||
#define QXLSX_XLSXCELLFORMULA_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QExplicitlySharedDataPointer>
|
||||
|
||||
class QXmlStreamWriter;
|
||||
class QXmlStreamReader;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class CellFormulaPrivate;
|
||||
class CellRange;
|
||||
class Worksheet;
|
||||
class WorksheetPrivate;
|
||||
|
||||
class QXLSX_EXPORT CellFormula
|
||||
{
|
||||
public:
|
||||
enum FormulaType { NormalType, ArrayType, DataTableType, SharedType };
|
||||
|
||||
public:
|
||||
CellFormula();
|
||||
CellFormula(const char *formula, FormulaType type = NormalType);
|
||||
CellFormula(const QString &formula, FormulaType type = NormalType);
|
||||
CellFormula(const QString &formula, const CellRange &ref, FormulaType type);
|
||||
CellFormula(const CellFormula &other);
|
||||
~CellFormula();
|
||||
|
||||
public:
|
||||
CellFormula &operator=(const CellFormula &other);
|
||||
bool isValid() const;
|
||||
|
||||
FormulaType formulaType() const;
|
||||
QString formulaText() const;
|
||||
CellRange reference() const;
|
||||
int sharedIndex() const;
|
||||
|
||||
bool operator==(const CellFormula &formula) const;
|
||||
bool operator!=(const CellFormula &formula) const;
|
||||
|
||||
bool saveToXml(QXmlStreamWriter &writer) const;
|
||||
bool loadFromXml(QXmlStreamReader &reader);
|
||||
|
||||
private:
|
||||
friend class Worksheet;
|
||||
friend class WorksheetPrivate;
|
||||
QExplicitlySharedDataPointer<CellFormulaPrivate> d;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_XLSXCELLFORMULA_H
|
|
@ -0,0 +1,33 @@
|
|||
// xlsxcellformula_p.h
|
||||
|
||||
#ifndef XLSXCELLFORMULA_P_H
|
||||
#define XLSXCELLFORMULA_P_H
|
||||
|
||||
#include "xlsxcellformula.h"
|
||||
#include "xlsxcellrange.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QSharedData>
|
||||
#include <QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class CellFormulaPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
CellFormulaPrivate(const QString &formula,
|
||||
const CellRange &reference,
|
||||
CellFormula::FormulaType type);
|
||||
CellFormulaPrivate(const CellFormulaPrivate &other);
|
||||
~CellFormulaPrivate();
|
||||
|
||||
QString formula; // formula contents
|
||||
CellFormula::FormulaType type;
|
||||
CellRange reference;
|
||||
bool ca; // Calculate Cell
|
||||
int si; // Shared group index
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXCELLFORMULA_P_H
|
|
@ -0,0 +1,32 @@
|
|||
// xlsxcelllocation.h
|
||||
|
||||
#ifndef CELL_LOCATION_H
|
||||
#define CELL_LOCATION_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QList>
|
||||
#include <QMetaType>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Cell;
|
||||
|
||||
class QXLSX_EXPORT CellLocation
|
||||
{
|
||||
public:
|
||||
CellLocation();
|
||||
|
||||
int col;
|
||||
int row;
|
||||
|
||||
std::shared_ptr<Cell> cell;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
// xlsxcellrange.h
|
||||
|
||||
#ifndef QXLSX_XLSXCELLRANGE_H
|
||||
#define QXLSX_XLSXCELLRANGE_H
|
||||
|
||||
#include "xlsxcellreference.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
// dev57
|
||||
class QXLSX_EXPORT CellRange
|
||||
{
|
||||
public:
|
||||
CellRange();
|
||||
CellRange(int firstRow, int firstColumn, int lastRow, int lastColumn);
|
||||
CellRange(const CellReference &topLeft, const CellReference &bottomRight);
|
||||
CellRange(const QString &range);
|
||||
CellRange(const char *range);
|
||||
CellRange(const CellRange &other);
|
||||
~CellRange();
|
||||
|
||||
QString toString(bool row_abs = false, bool col_abs = false) const;
|
||||
bool isValid() const;
|
||||
inline void setFirstRow(int row) { top = row; }
|
||||
inline void setLastRow(int row) { bottom = row; }
|
||||
inline void setFirstColumn(int col) { left = col; }
|
||||
inline void setLastColumn(int col) { right = col; }
|
||||
inline int firstRow() const { return top; }
|
||||
inline int lastRow() const { return bottom; }
|
||||
inline int firstColumn() const { return left; }
|
||||
inline int lastColumn() const { return right; }
|
||||
inline int rowCount() const { return bottom - top + 1; }
|
||||
inline int columnCount() const { return right - left + 1; }
|
||||
inline CellReference topLeft() const { return CellReference(top, left); }
|
||||
inline CellReference topRight() const { return CellReference(top, right); }
|
||||
inline CellReference bottomLeft() const { return CellReference(bottom, left); }
|
||||
inline CellReference bottomRight() const { return CellReference(bottom, right); }
|
||||
|
||||
inline void operator=(const CellRange &other)
|
||||
{
|
||||
top = other.top;
|
||||
bottom = other.bottom;
|
||||
left = other.left;
|
||||
right = other.right;
|
||||
}
|
||||
inline bool operator==(const CellRange &other) const
|
||||
{
|
||||
return top == other.top && bottom == other.bottom && left == other.left &&
|
||||
right == other.right;
|
||||
}
|
||||
inline bool operator!=(const CellRange &other) const
|
||||
{
|
||||
return top != other.top || bottom != other.bottom || left != other.left ||
|
||||
right != other.right;
|
||||
}
|
||||
|
||||
private:
|
||||
void init(const QString &range);
|
||||
|
||||
int top;
|
||||
int left;
|
||||
int bottom;
|
||||
int right;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
Q_DECLARE_TYPEINFO(QXlsx::CellRange, Q_MOVABLE_TYPE);
|
||||
|
||||
#endif // QXLSX_XLSXCELLRANGE_H
|
|
@ -0,0 +1,58 @@
|
|||
// xlsxcellreference.h
|
||||
|
||||
#ifndef QXLSX_XLSXCELLREFERENCE_H
|
||||
#define QXLSX_XLSXCELLREFERENCE_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class QXLSX_EXPORT CellReference
|
||||
{
|
||||
public:
|
||||
CellReference();
|
||||
/*!
|
||||
Constructs the Reference from the given \a row, and \a column.
|
||||
*/
|
||||
constexpr CellReference(int row, int column)
|
||||
: _row(row)
|
||||
, _column(column)
|
||||
{
|
||||
}
|
||||
CellReference(const QString &cell);
|
||||
CellReference(const char *cell);
|
||||
CellReference(const CellReference &other);
|
||||
~CellReference();
|
||||
|
||||
QString toString(bool row_abs = false, bool col_abs = false) const;
|
||||
bool isValid() const;
|
||||
inline void setRow(int row) { _row = row; }
|
||||
inline void setColumn(int col) { _column = col; }
|
||||
inline int row() const { return _row; }
|
||||
inline int column() const { return _column; }
|
||||
|
||||
inline bool operator==(const CellReference &other) const
|
||||
{
|
||||
return _row == other._row && _column == other._column;
|
||||
}
|
||||
inline bool operator!=(const CellReference &other) const
|
||||
{
|
||||
return _row != other._row || _column != other._column;
|
||||
}
|
||||
|
||||
inline bool operator>(const CellReference &other) const
|
||||
{
|
||||
return _row > other._row || _column != other._column;
|
||||
}
|
||||
|
||||
private:
|
||||
void init(const QString &cell);
|
||||
int _row{-1};
|
||||
int _column{-1};
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
Q_DECLARE_TYPEINFO(QXlsx::CellReference, Q_MOVABLE_TYPE);
|
||||
|
||||
#endif // QXLSX_XLSXCELLREFERENCE_H
|
|
@ -0,0 +1,76 @@
|
|||
// xlsxchart.h
|
||||
|
||||
#ifndef QXLSX_CHART_H
|
||||
#define QXLSX_CHART_H
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class AbstractSheet;
|
||||
class Worksheet;
|
||||
class ChartPrivate;
|
||||
class CellRange;
|
||||
class DrawingAnchor;
|
||||
|
||||
class QXLSX_EXPORT Chart : public AbstractOOXmlFile
|
||||
{
|
||||
Q_DECLARE_PRIVATE(Chart)
|
||||
public:
|
||||
enum ChartType { // 16 type of chart (ECMA 376)
|
||||
CT_NoStatementChart = 0, // Zero is internally used for unknown types
|
||||
CT_AreaChart,
|
||||
CT_Area3DChart,
|
||||
CT_LineChart,
|
||||
CT_Line3DChart,
|
||||
CT_StockChart,
|
||||
CT_RadarChart,
|
||||
CT_ScatterChart,
|
||||
CT_PieChart,
|
||||
CT_Pie3DChart,
|
||||
CT_DoughnutChart,
|
||||
CT_BarChart,
|
||||
CT_Bar3DChart,
|
||||
CT_OfPieChart,
|
||||
CT_SurfaceChart,
|
||||
CT_Surface3DChart,
|
||||
CT_BubbleChart,
|
||||
};
|
||||
enum ChartAxisPos { None = (-1), Left = 0, Right, Top, Bottom };
|
||||
|
||||
private:
|
||||
friend class AbstractSheet;
|
||||
friend class Worksheet;
|
||||
friend class Chartsheet;
|
||||
friend class DrawingAnchor;
|
||||
|
||||
private:
|
||||
Chart(AbstractSheet *parent, CreateFlag flag);
|
||||
|
||||
public:
|
||||
~Chart();
|
||||
|
||||
public:
|
||||
void addSeries(const CellRange &range,
|
||||
AbstractSheet *sheet = nullptr,
|
||||
bool headerH = false,
|
||||
bool headerV = false,
|
||||
bool swapHeaders = false);
|
||||
void setChartType(ChartType type);
|
||||
void setChartStyle(int id);
|
||||
void setAxisTitle(Chart::ChartAxisPos pos, QString axisTitle);
|
||||
void setChartTitle(QString strchartTitle);
|
||||
void setChartLegend(Chart::ChartAxisPos legendPos, bool overlap = false);
|
||||
void setGridlinesEnable(bool majorGridlinesEnable = false, bool minorGridlinesEnable = false);
|
||||
|
||||
public:
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_CHART_H
|
|
@ -0,0 +1,148 @@
|
|||
// xlsxchart_p.h
|
||||
|
||||
#ifndef QXLSX_CHART_P_H
|
||||
#define QXLSX_CHART_P_H
|
||||
|
||||
#include "xlsxabstractooxmlfile_p.h"
|
||||
#include "xlsxchart.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class XlsxSeries
|
||||
{
|
||||
public:
|
||||
// At present, we care about number cell ranges only!
|
||||
QString numberDataSource_numRef; // yval, val
|
||||
QString axDataSource_numRef; // xval, cat
|
||||
QString headerH_numRef;
|
||||
QString headerV_numRef;
|
||||
bool swapHeader = false;
|
||||
};
|
||||
|
||||
class XlsxAxis
|
||||
{
|
||||
public:
|
||||
enum Type { T_None = (-1), T_Cat, T_Val, T_Date, T_Ser };
|
||||
enum AxisPos { None = (-1), Left, Right, Top, Bottom };
|
||||
|
||||
public:
|
||||
XlsxAxis() {}
|
||||
|
||||
XlsxAxis(Type t, XlsxAxis::AxisPos p, int id, int crossId, QString axisTitle = QString())
|
||||
{
|
||||
type = t;
|
||||
axisPos = p;
|
||||
axisId = id;
|
||||
crossAx = crossId;
|
||||
|
||||
if (!axisTitle.isEmpty()) {
|
||||
axisNames[p] = axisTitle;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Type type;
|
||||
XlsxAxis::AxisPos axisPos;
|
||||
int axisId;
|
||||
int crossAx;
|
||||
QMap<XlsxAxis::AxisPos, QString> axisNames;
|
||||
};
|
||||
|
||||
class ChartPrivate : public AbstractOOXmlFilePrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(Chart)
|
||||
|
||||
public:
|
||||
ChartPrivate(Chart *q, Chart::CreateFlag flag);
|
||||
~ChartPrivate();
|
||||
|
||||
public:
|
||||
bool loadXmlChart(QXmlStreamReader &reader);
|
||||
bool loadXmlPlotArea(QXmlStreamReader &reader);
|
||||
|
||||
protected:
|
||||
bool loadXmlPlotAreaElement(QXmlStreamReader &reader);
|
||||
|
||||
public:
|
||||
bool loadXmlXxxChart(QXmlStreamReader &reader);
|
||||
bool loadXmlSer(QXmlStreamReader &reader);
|
||||
QString loadXmlNumRef(QXmlStreamReader &reader);
|
||||
QString loadXmlStrRef(QXmlStreamReader &reader);
|
||||
bool loadXmlChartTitle(QXmlStreamReader &reader);
|
||||
bool loadXmlChartLegend(QXmlStreamReader &reader);
|
||||
|
||||
protected:
|
||||
bool loadXmlChartTitleTx(QXmlStreamReader &reader);
|
||||
bool loadXmlChartTitleTxRich(QXmlStreamReader &reader);
|
||||
bool loadXmlChartTitleTxRichP(QXmlStreamReader &reader);
|
||||
bool loadXmlChartTitleTxRichP_R(QXmlStreamReader &reader);
|
||||
|
||||
protected:
|
||||
bool loadXmlAxisCatAx(QXmlStreamReader &reader);
|
||||
bool loadXmlAxisDateAx(QXmlStreamReader &reader);
|
||||
bool loadXmlAxisSerAx(QXmlStreamReader &reader);
|
||||
bool loadXmlAxisValAx(QXmlStreamReader &reader);
|
||||
bool loadXmlAxisEG_AxShared(QXmlStreamReader &reader, XlsxAxis *axis);
|
||||
bool loadXmlAxisEG_AxShared_Scaling(QXmlStreamReader &reader, XlsxAxis *axis);
|
||||
bool loadXmlAxisEG_AxShared_Title(QXmlStreamReader &reader, XlsxAxis *axis);
|
||||
bool loadXmlAxisEG_AxShared_Title_Overlay(QXmlStreamReader &reader, XlsxAxis *axis);
|
||||
bool loadXmlAxisEG_AxShared_Title_Tx(QXmlStreamReader &reader, XlsxAxis *axis);
|
||||
bool loadXmlAxisEG_AxShared_Title_Tx_Rich(QXmlStreamReader &reader, XlsxAxis *axis);
|
||||
bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P(QXmlStreamReader &reader, XlsxAxis *axis);
|
||||
bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P_pPr(QXmlStreamReader &reader, XlsxAxis *axis);
|
||||
bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(QXmlStreamReader &reader, XlsxAxis *axis);
|
||||
|
||||
QString readSubTree(QXmlStreamReader &reader);
|
||||
|
||||
public:
|
||||
void saveXmlChart(QXmlStreamWriter &writer) const;
|
||||
void saveXmlChartTitle(QXmlStreamWriter &writer) const;
|
||||
void saveXmlPieChart(QXmlStreamWriter &writer) const;
|
||||
void saveXmlBarChart(QXmlStreamWriter &writer) const;
|
||||
void saveXmlLineChart(QXmlStreamWriter &writer) const;
|
||||
void saveXmlScatterChart(QXmlStreamWriter &writer) const;
|
||||
void saveXmlAreaChart(QXmlStreamWriter &writer) const;
|
||||
void saveXmlDoughnutChart(QXmlStreamWriter &writer) const;
|
||||
void saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const;
|
||||
void saveXmlAxis(QXmlStreamWriter &writer) const;
|
||||
void saveXmlChartLegend(QXmlStreamWriter &writer) const;
|
||||
|
||||
protected:
|
||||
void saveXmlAxisCatAx(QXmlStreamWriter &writer, XlsxAxis *axis) const;
|
||||
void saveXmlAxisDateAx(QXmlStreamWriter &writer, XlsxAxis *axis) const;
|
||||
void saveXmlAxisSerAx(QXmlStreamWriter &writer, XlsxAxis *axis) const;
|
||||
void saveXmlAxisValAx(QXmlStreamWriter &writer, XlsxAxis *axis) const;
|
||||
|
||||
void saveXmlAxisEG_AxShared(QXmlStreamWriter &writer, XlsxAxis *axis) const;
|
||||
void saveXmlAxisEG_AxShared_Title(QXmlStreamWriter &writer, XlsxAxis *axis) const;
|
||||
QString GetAxisPosString(XlsxAxis::AxisPos axisPos) const;
|
||||
QString GetAxisName(XlsxAxis *ptrXlsxAxis) const;
|
||||
|
||||
public:
|
||||
Chart::ChartType chartType;
|
||||
QList<std::shared_ptr<XlsxSeries>> seriesList;
|
||||
QList<std::shared_ptr<XlsxAxis>> axisList;
|
||||
QMap<XlsxAxis::AxisPos, QString> axisNames;
|
||||
QString chartTitle;
|
||||
AbstractSheet *sheet;
|
||||
Chart::ChartAxisPos legendPos;
|
||||
bool legendOverlay;
|
||||
bool majorGridlinesEnabled;
|
||||
bool minorGridlinesEnabled;
|
||||
|
||||
QString layout; // only for storing a read file
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_CHART_P_H
|
|
@ -0,0 +1,37 @@
|
|||
// xlsxchartsheet.h
|
||||
|
||||
#ifndef XLSXCHARTSHEET_H
|
||||
#define XLSXCHARTSHEET_H
|
||||
|
||||
#include "xlsxabstractsheet.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Workbook;
|
||||
class DocumentPrivate;
|
||||
class ChartsheetPrivate;
|
||||
class Chart;
|
||||
|
||||
class QXLSX_EXPORT Chartsheet : public AbstractSheet
|
||||
{
|
||||
Q_DECLARE_PRIVATE(Chartsheet)
|
||||
|
||||
public:
|
||||
~Chartsheet();
|
||||
Chart *chart();
|
||||
|
||||
private:
|
||||
friend class DocumentPrivate;
|
||||
friend class Workbook;
|
||||
|
||||
Chartsheet(const QString &sheetName, int sheetId, Workbook *book, CreateFlag flag);
|
||||
Chartsheet *copy(const QString &distName, int distId) const override;
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif // XLSXCHARTSHEET_H
|
|
@ -0,0 +1,23 @@
|
|||
// xlsxchartsheet_p.h
|
||||
|
||||
#ifndef XLSXCHARTSHEET_P_H
|
||||
#define XLSXCHARTSHEET_P_H
|
||||
|
||||
#include "xlsxabstractsheet_p.h"
|
||||
#include "xlsxchartsheet.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class ChartsheetPrivate : public AbstractSheetPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(Chartsheet)
|
||||
public:
|
||||
ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag);
|
||||
~ChartsheetPrivate();
|
||||
|
||||
Chart *chart;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif // XLSXCHARTSHEET_P_H
|
|
@ -0,0 +1,58 @@
|
|||
// xlsxcolor_p.h
|
||||
|
||||
#ifndef QXLSX_XLSXCOLOR_P_H
|
||||
#define QXLSX_XLSXCOLOR_P_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QVariant>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Styles;
|
||||
|
||||
class XlsxColor
|
||||
{
|
||||
public:
|
||||
explicit XlsxColor(const QColor &color = QColor());
|
||||
explicit XlsxColor(const QString &theme, const QString &tint = QString());
|
||||
explicit XlsxColor(int index);
|
||||
|
||||
bool isThemeColor() const;
|
||||
bool isIndexedColor() const;
|
||||
bool isRgbColor() const;
|
||||
bool isInvalid() const;
|
||||
|
||||
QColor rgbColor() const;
|
||||
int indexedColor() const;
|
||||
QStringList themeColor() const;
|
||||
|
||||
operator QVariant() const;
|
||||
|
||||
static QColor fromARGBString(const QString &c);
|
||||
static QString toARGBString(const QColor &c);
|
||||
|
||||
bool saveToXml(QXmlStreamWriter &writer, const QString &node = QString()) const;
|
||||
bool loadFromXml(QXmlStreamReader &reader);
|
||||
|
||||
private:
|
||||
QVariant val;
|
||||
};
|
||||
|
||||
#if !defined(QT_NO_DATASTREAM)
|
||||
QDataStream &operator<<(QDataStream &, const XlsxColor &);
|
||||
QDataStream &operator>>(QDataStream &, XlsxColor &);
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
QDebug operator<<(QDebug dbg, const XlsxColor &c);
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
Q_DECLARE_METATYPE(QXlsx::XlsxColor)
|
||||
|
||||
#endif // QXLSX_XLSXCOLOR_P_H
|
|
@ -0,0 +1,130 @@
|
|||
// xlsxconditionalformatting.h
|
||||
|
||||
#ifndef QXLSX_XLSXCONDITIONALFORMATTING_H
|
||||
#define QXLSX_XLSXCONDITIONALFORMATTING_H
|
||||
|
||||
#include "xlsxcellrange.h"
|
||||
#include "xlsxcellreference.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QList>
|
||||
#include <QSharedDataPointer>
|
||||
#include <QString>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
class ConditionalFormattingTest;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Format;
|
||||
class Worksheet;
|
||||
class Styles;
|
||||
class ConditionalFormattingPrivate;
|
||||
|
||||
class QXLSX_EXPORT ConditionalFormatting
|
||||
{
|
||||
public:
|
||||
enum HighlightRuleType {
|
||||
Highlight_LessThan,
|
||||
Highlight_LessThanOrEqual,
|
||||
Highlight_Equal,
|
||||
Highlight_NotEqual,
|
||||
Highlight_GreaterThanOrEqual,
|
||||
Highlight_GreaterThan,
|
||||
Highlight_Between,
|
||||
Highlight_NotBetween,
|
||||
|
||||
Highlight_ContainsText,
|
||||
Highlight_NotContainsText,
|
||||
Highlight_BeginsWith,
|
||||
Highlight_EndsWith,
|
||||
|
||||
Highlight_TimePeriod,
|
||||
|
||||
Highlight_Duplicate,
|
||||
Highlight_Unique,
|
||||
Highlight_Blanks,
|
||||
Highlight_NoBlanks,
|
||||
Highlight_Errors,
|
||||
Highlight_NoErrors,
|
||||
|
||||
Highlight_Top,
|
||||
Highlight_TopPercent,
|
||||
Highlight_Bottom,
|
||||
Highlight_BottomPercent,
|
||||
|
||||
Highlight_AboveAverage,
|
||||
Highlight_AboveOrEqualAverage,
|
||||
Highlight_AboveStdDev1,
|
||||
Highlight_AboveStdDev2,
|
||||
Highlight_AboveStdDev3,
|
||||
Highlight_BelowAverage,
|
||||
Highlight_BelowOrEqualAverage,
|
||||
Highlight_BelowStdDev1,
|
||||
Highlight_BelowStdDev2,
|
||||
Highlight_BelowStdDev3,
|
||||
|
||||
Highlight_Expression
|
||||
};
|
||||
|
||||
enum ValueObjectType { VOT_Formula, VOT_Max, VOT_Min, VOT_Num, VOT_Percent, VOT_Percentile };
|
||||
|
||||
public:
|
||||
ConditionalFormatting();
|
||||
ConditionalFormatting(const ConditionalFormatting &other);
|
||||
~ConditionalFormatting();
|
||||
|
||||
public:
|
||||
bool addHighlightCellsRule(HighlightRuleType type,
|
||||
const Format &format,
|
||||
bool stopIfTrue = false);
|
||||
bool addHighlightCellsRule(HighlightRuleType type,
|
||||
const QString &formula1,
|
||||
const Format &format,
|
||||
bool stopIfTrue = false);
|
||||
bool addHighlightCellsRule(HighlightRuleType type,
|
||||
const QString &formula1,
|
||||
const QString &formula2,
|
||||
const Format &format,
|
||||
bool stopIfTrue = false);
|
||||
bool addDataBarRule(const QColor &color, bool showData = true, bool stopIfTrue = false);
|
||||
bool addDataBarRule(const QColor &color,
|
||||
ValueObjectType type1,
|
||||
const QString &val1,
|
||||
ValueObjectType type2,
|
||||
const QString &val2,
|
||||
bool showData = true,
|
||||
bool stopIfTrue = false);
|
||||
bool
|
||||
add2ColorScaleRule(const QColor &minColor, const QColor &maxColor, bool stopIfTrue = false);
|
||||
bool add3ColorScaleRule(const QColor &minColor,
|
||||
const QColor &midColor,
|
||||
const QColor &maxColor,
|
||||
bool stopIfTrue = false);
|
||||
|
||||
QList<CellRange> ranges() const;
|
||||
|
||||
void addCell(const CellReference &cell);
|
||||
void addCell(int row, int col);
|
||||
void addRange(int firstRow, int firstCol, int lastRow, int lastCol);
|
||||
void addRange(const CellRange &range);
|
||||
|
||||
// needed by QSharedDataPointer!!
|
||||
ConditionalFormatting &operator=(const ConditionalFormatting &other);
|
||||
|
||||
private:
|
||||
friend class Worksheet;
|
||||
friend class ::ConditionalFormattingTest;
|
||||
|
||||
private:
|
||||
bool saveToXml(QXmlStreamWriter &writer) const;
|
||||
bool loadFromXml(QXmlStreamReader &reader, Styles *styles = nullptr);
|
||||
|
||||
QSharedDataPointer<ConditionalFormattingPrivate> d;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_XLSXCONDITIONALFORMATTING_H
|
|
@ -0,0 +1,102 @@
|
|||
// xlsxconditionalformatting_p.h
|
||||
|
||||
#ifndef XLSXCONDITIONALFORMATTING_P_H
|
||||
#define XLSXCONDITIONALFORMATTING_P_H
|
||||
|
||||
#include "xlsxcolor_p.h"
|
||||
#include "xlsxconditionalformatting.h"
|
||||
#include "xlsxformat.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QMap>
|
||||
#include <QSharedData>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class XlsxCfVoData
|
||||
{
|
||||
public:
|
||||
XlsxCfVoData()
|
||||
: gte(true)
|
||||
{
|
||||
}
|
||||
|
||||
XlsxCfVoData(ConditionalFormatting::ValueObjectType type, const QString &value, bool gte = true)
|
||||
: type(type)
|
||||
, value(value)
|
||||
, gte(gte)
|
||||
{
|
||||
}
|
||||
|
||||
ConditionalFormatting::ValueObjectType type;
|
||||
QString value;
|
||||
bool gte;
|
||||
};
|
||||
|
||||
class XlsxCfRuleData
|
||||
{
|
||||
public:
|
||||
enum Attribute {
|
||||
A_type,
|
||||
A_dxfId,
|
||||
// A_priority,
|
||||
A_stopIfTrue,
|
||||
A_aboveAverage,
|
||||
A_percent,
|
||||
A_bottom,
|
||||
A_operator,
|
||||
A_text,
|
||||
A_timePeriod,
|
||||
A_rank,
|
||||
A_stdDev,
|
||||
A_equalAverage,
|
||||
|
||||
A_dxfFormat,
|
||||
A_formula1,
|
||||
A_formula2,
|
||||
A_formula3,
|
||||
A_formula1_temp,
|
||||
|
||||
A_color1,
|
||||
A_color2,
|
||||
A_color3,
|
||||
|
||||
A_cfvo1,
|
||||
A_cfvo2,
|
||||
A_cfvo3,
|
||||
|
||||
A_hideData
|
||||
};
|
||||
|
||||
XlsxCfRuleData()
|
||||
: priority(1)
|
||||
{
|
||||
}
|
||||
|
||||
int priority;
|
||||
Format dxfFormat;
|
||||
QMap<int, QVariant> attrs;
|
||||
};
|
||||
|
||||
class ConditionalFormattingPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
ConditionalFormattingPrivate();
|
||||
ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other);
|
||||
~ConditionalFormattingPrivate();
|
||||
|
||||
void writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData &cfvo) const;
|
||||
bool readCfVo(QXmlStreamReader &reader, XlsxCfVoData &cfvo);
|
||||
bool readCfRule(QXmlStreamReader &reader, XlsxCfRuleData *cfRule, Styles *styles);
|
||||
bool readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *cfRule);
|
||||
bool readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *cfRule);
|
||||
|
||||
QList<std::shared_ptr<XlsxCfRuleData>> cfRules;
|
||||
QList<CellRange> ranges;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
Q_DECLARE_METATYPE(QXlsx::XlsxCfVoData)
|
||||
#endif // XLSXCONDITIONALFORMATTING_P_H
|
|
@ -0,0 +1,55 @@
|
|||
// xlsxcontenttypes_p.h
|
||||
|
||||
#ifndef XLSXCONTENTTYPES_H
|
||||
#define XLSXCONTENTTYPES_H
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class ContentTypes : public AbstractOOXmlFile
|
||||
{
|
||||
public:
|
||||
ContentTypes(CreateFlag flag);
|
||||
|
||||
void addDefault(const QString &key, const QString &value);
|
||||
void addOverride(const QString &key, const QString &value);
|
||||
|
||||
// Convenient function for addOverride()
|
||||
void addDocPropCore();
|
||||
void addDocPropApp();
|
||||
void addStyles();
|
||||
void addTheme();
|
||||
void addWorkbook();
|
||||
void addWorksheetName(const QString &name);
|
||||
void addChartsheetName(const QString &name);
|
||||
void addChartName(const QString &name);
|
||||
void addDrawingName(const QString &name);
|
||||
void addCommentName(const QString &name);
|
||||
void addTableName(const QString &name);
|
||||
void addExternalLinkName(const QString &name);
|
||||
void addSharedString();
|
||||
void addVmlName();
|
||||
void addCalcChain();
|
||||
void addVbaProject();
|
||||
|
||||
void clearOverrides();
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
|
||||
private:
|
||||
QMap<QString, QString> m_defaults;
|
||||
QMap<QString, QString> m_overrides;
|
||||
|
||||
QString m_package_prefix;
|
||||
QString m_document_prefix;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif // XLSXCONTENTTYPES_H
|
|
@ -0,0 +1,92 @@
|
|||
// xlsxvalidation.h
|
||||
|
||||
#ifndef QXLSX_XLSXDATAVALIDATION_H
|
||||
#define QXLSX_XLSXDATAVALIDATION_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QSharedDataPointer>
|
||||
#include <QString>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
class QXmlStreamReader;
|
||||
class QXmlStreamWriter;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Worksheet;
|
||||
class CellRange;
|
||||
class CellReference;
|
||||
|
||||
class DataValidationPrivate;
|
||||
class QXLSX_EXPORT DataValidation
|
||||
{
|
||||
public:
|
||||
enum ValidationType { None, Whole, Decimal, List, Date, Time, TextLength, Custom };
|
||||
|
||||
enum ValidationOperator {
|
||||
Between,
|
||||
NotBetween,
|
||||
Equal,
|
||||
NotEqual,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
GreaterThan,
|
||||
GreaterThanOrEqual
|
||||
};
|
||||
|
||||
enum ErrorStyle { Stop, Warning, Information };
|
||||
|
||||
DataValidation();
|
||||
DataValidation(ValidationType type,
|
||||
ValidationOperator op = Between,
|
||||
const QString &formula1 = QString(),
|
||||
const QString &formula2 = QString(),
|
||||
bool allowBlank = false);
|
||||
DataValidation(const DataValidation &other);
|
||||
~DataValidation();
|
||||
|
||||
ValidationType validationType() const;
|
||||
ValidationOperator validationOperator() const;
|
||||
ErrorStyle errorStyle() const;
|
||||
QString formula1() const;
|
||||
QString formula2() const;
|
||||
bool allowBlank() const;
|
||||
QString errorMessage() const;
|
||||
QString errorMessageTitle() const;
|
||||
QString promptMessage() const;
|
||||
QString promptMessageTitle() const;
|
||||
bool isPromptMessageVisible() const;
|
||||
bool isErrorMessageVisible() const;
|
||||
QList<CellRange> ranges() const;
|
||||
|
||||
void setValidationType(ValidationType type);
|
||||
void setValidationOperator(ValidationOperator op);
|
||||
void setErrorStyle(ErrorStyle es);
|
||||
void setFormula1(const QString &formula);
|
||||
void setFormula2(const QString &formula);
|
||||
void setErrorMessage(const QString &error, const QString &title = QString());
|
||||
void setPromptMessage(const QString &prompt, const QString &title = QString());
|
||||
void setAllowBlank(bool enable);
|
||||
void setPromptMessageVisible(bool visible);
|
||||
void setErrorMessageVisible(bool visible);
|
||||
|
||||
void addCell(const CellReference &cell);
|
||||
void addCell(int row, int col);
|
||||
void addRange(int firstRow, int firstCol, int lastRow, int lastCol);
|
||||
void addRange(const CellRange &range);
|
||||
|
||||
DataValidation &operator=(const DataValidation &other);
|
||||
|
||||
bool saveToXml(QXmlStreamWriter &writer) const;
|
||||
static DataValidation loadFromXml(QXmlStreamReader &reader);
|
||||
|
||||
private:
|
||||
QSharedDataPointer<DataValidationPrivate> d;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_XLSXDATAVALIDATION_H
|
|
@ -0,0 +1,40 @@
|
|||
// xlsxdatavalidation_p.h
|
||||
|
||||
#ifndef XLSXDATAVALIDATION_P_H
|
||||
#define XLSXDATAVALIDATION_P_H
|
||||
|
||||
#include "xlsxdatavalidation.h"
|
||||
|
||||
#include <QSharedData>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class DataValidationPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
DataValidationPrivate();
|
||||
DataValidationPrivate(DataValidation::ValidationType type,
|
||||
DataValidation::ValidationOperator op,
|
||||
const QString &formula1,
|
||||
const QString &formula2,
|
||||
bool allowBlank);
|
||||
DataValidationPrivate(const DataValidationPrivate &other);
|
||||
~DataValidationPrivate();
|
||||
|
||||
DataValidation::ValidationType validationType;
|
||||
DataValidation::ValidationOperator validationOperator;
|
||||
DataValidation::ErrorStyle errorStyle;
|
||||
bool allowBlank;
|
||||
bool isPromptMessageVisible;
|
||||
bool isErrorMessageVisible;
|
||||
QString formula1;
|
||||
QString formula2;
|
||||
QString errorMessage;
|
||||
QString errorMessageTitle;
|
||||
QString promptMessage;
|
||||
QString promptMessageTitle;
|
||||
QList<CellRange> ranges;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif // XLSXDATAVALIDATION_P_H
|
|
@ -0,0 +1,47 @@
|
|||
// xlsxdatetype.h
|
||||
|
||||
#ifndef QXLSX_XLSXDATETYPE_H
|
||||
#define QXLSX_XLSXDATETYPE_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTime>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class QXLSX_EXPORT DateType
|
||||
{
|
||||
public:
|
||||
DateType();
|
||||
/*
|
||||
DateType(bool is1904 = false);
|
||||
DateType(double d, bool is1904 = false);
|
||||
DateType(QDateTime qdt, bool is1904 = false);
|
||||
DateType(QDate qd, bool is1904 = false);
|
||||
DateType(QTime qt, bool is1904 = false);
|
||||
public:
|
||||
enum currentDateType { DateAndTimeType, OnlyDateType, OnlyTimeType };
|
||||
public:
|
||||
currentDateType getType();
|
||||
bool getValue(QDateTime* pQdt);
|
||||
bool getValue(QDate* pQd);
|
||||
bool getValue(QTime* pQt);
|
||||
bool getValue(double* pD);
|
||||
|
||||
protected:
|
||||
|
||||
protected:
|
||||
bool isSet;
|
||||
double dValue;
|
||||
bool is1904Type;
|
||||
currentDateType dType;
|
||||
*/
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
// xlsxdocpropsapp_p.h
|
||||
|
||||
#ifndef XLSXDOCPROPSAPP_H
|
||||
#define XLSXDOCPROPSAPP_H
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class DocPropsApp : public AbstractOOXmlFile
|
||||
{
|
||||
public:
|
||||
DocPropsApp(CreateFlag flag);
|
||||
|
||||
void addPartTitle(const QString &title);
|
||||
void addHeadingPair(const QString &name, int value);
|
||||
|
||||
bool setProperty(const QString &name, const QString &value);
|
||||
QString property(const QString &name) const;
|
||||
QStringList propertyNames() const;
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
|
||||
private:
|
||||
QStringList m_titlesOfPartsList;
|
||||
QList<std::pair<QString, int>> m_headingPairsList;
|
||||
QMap<QString, QString> m_properties;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXDOCPROPSAPP_H
|
|
@ -0,0 +1,34 @@
|
|||
// xlsxdocpropscore_p.h
|
||||
|
||||
#ifndef XLSXDOCPROPSCORE_H
|
||||
#define XLSXDOCPROPSCORE_H
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class DocPropsCore : public AbstractOOXmlFile
|
||||
{
|
||||
public:
|
||||
explicit DocPropsCore(CreateFlag flag);
|
||||
|
||||
bool setProperty(const QString &name, const QString &value);
|
||||
QString property(const QString &name) const;
|
||||
QStringList propertyNames() const;
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
|
||||
private:
|
||||
QMap<QString, QString> m_properties;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXDOCPROPSCORE_H
|
|
@ -0,0 +1,146 @@
|
|||
// xlsxdocument.h
|
||||
|
||||
#ifndef QXLSX_XLSXDOCUMENT_H
|
||||
#define QXLSX_XLSXDOCUMENT_H
|
||||
|
||||
#include "xlsxformat.h"
|
||||
#include "xlsxglobal.h"
|
||||
#include "xlsxworksheet.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QImage>
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Workbook;
|
||||
class Cell;
|
||||
class CellRange;
|
||||
class DataValidation;
|
||||
class ConditionalFormatting;
|
||||
class Chart;
|
||||
class CellReference;
|
||||
class DocumentPrivate;
|
||||
|
||||
class QXLSX_EXPORT Document : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(Document) // D-Pointer. Qt classes have a Q_DECLARE_PRIVATE
|
||||
// macro in the public class. The macro reads: qglobal.h
|
||||
public:
|
||||
explicit Document(QObject *parent = nullptr);
|
||||
Document(const QString &xlsxName, QObject *parent = nullptr);
|
||||
Document(QIODevice *device, QObject *parent = nullptr);
|
||||
~Document();
|
||||
|
||||
bool write(const CellReference &cell, const QVariant &value, const Format &format = Format());
|
||||
bool write(int row, int col, const QVariant &value, const Format &format = Format());
|
||||
|
||||
QVariant read(const CellReference &cell) const;
|
||||
QVariant read(int row, int col) const;
|
||||
|
||||
int insertImage(int row, int col, const QImage &image);
|
||||
bool getImage(int imageIndex, QImage &img);
|
||||
bool getImage(int row, int col, QImage &img);
|
||||
uint getImageCount();
|
||||
|
||||
Chart *insertChart(int row, int col, const QSize &size);
|
||||
|
||||
bool mergeCells(const CellRange &range, const Format &format = Format());
|
||||
bool unmergeCells(const CellRange &range);
|
||||
|
||||
bool setColumnWidth(const CellRange &range, double width);
|
||||
bool setColumnFormat(const CellRange &range, const Format &format);
|
||||
bool setColumnHidden(const CellRange &range, bool hidden);
|
||||
bool setColumnWidth(int column, double width);
|
||||
bool setColumnFormat(int column, const Format &format);
|
||||
bool setColumnHidden(int column, bool hidden);
|
||||
bool setColumnWidth(int colFirst, int colLast, double width);
|
||||
bool setColumnFormat(int colFirst, int colLast, const Format &format);
|
||||
bool setColumnHidden(int colFirst, int colLast, bool hidden);
|
||||
|
||||
double columnWidth(int column);
|
||||
Format columnFormat(int column);
|
||||
bool isColumnHidden(int column);
|
||||
|
||||
bool setRowHeight(int row, double height);
|
||||
bool setRowFormat(int row, const Format &format);
|
||||
bool setRowHidden(int row, bool hidden);
|
||||
bool setRowHeight(int rowFirst, int rowLast, double height);
|
||||
bool setRowFormat(int rowFirst, int rowLast, const Format &format);
|
||||
bool setRowHidden(int rowFirst, int rowLast, bool hidden);
|
||||
|
||||
double rowHeight(int row);
|
||||
Format rowFormat(int row);
|
||||
bool isRowHidden(int row);
|
||||
|
||||
bool groupRows(int rowFirst, int rowLast, bool collapsed = true);
|
||||
bool groupColumns(int colFirst, int colLast, bool collapsed = true);
|
||||
|
||||
bool addDataValidation(const DataValidation &validation);
|
||||
bool addConditionalFormatting(const ConditionalFormatting &cf);
|
||||
|
||||
std::shared_ptr<Cell> cellAt(const CellReference &cell) const;
|
||||
std::shared_ptr<Cell> cellAt(int row, int col) const;
|
||||
|
||||
bool defineName(const QString &name,
|
||||
const QString &formula,
|
||||
const QString &comment = QString(),
|
||||
const QString &scope = QString());
|
||||
|
||||
CellRange dimension() const;
|
||||
|
||||
QString documentProperty(const QString &name) const;
|
||||
void setDocumentProperty(const QString &name, const QString &property);
|
||||
QStringList documentPropertyNames() const;
|
||||
|
||||
QStringList sheetNames() const;
|
||||
bool addSheet(const QString &name = QString(),
|
||||
AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet);
|
||||
bool insertSheet(int index,
|
||||
const QString &name = QString(),
|
||||
AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet);
|
||||
bool selectSheet(const QString &name);
|
||||
bool selectSheet(int index);
|
||||
bool renameSheet(const QString &oldName, const QString &newName);
|
||||
bool copySheet(const QString &srcName, const QString &distName = QString());
|
||||
bool moveSheet(const QString &srcName, int distIndex);
|
||||
bool deleteSheet(const QString &name);
|
||||
|
||||
Workbook *workbook() const;
|
||||
AbstractSheet *sheet(const QString &sheetName) const;
|
||||
AbstractSheet *currentSheet() const;
|
||||
Worksheet *currentWorksheet() const;
|
||||
|
||||
bool save() const;
|
||||
bool saveAs(const QString &xlsXname) const;
|
||||
bool saveAs(QIODevice *device) const;
|
||||
|
||||
bool saveAsCsv(const QString mainCSVFileName) const;
|
||||
|
||||
// copy style from one xlsx file to other
|
||||
static bool copyStyle(const QString &from, const QString &to);
|
||||
|
||||
bool isLoadPackage() const;
|
||||
bool load() const; // equals to isLoadPackage()
|
||||
|
||||
bool changeimage(int filenoinmidea, QString newfile); // add by liufeijin20181025
|
||||
|
||||
bool autosizeColumnWidth(const CellRange &range);
|
||||
bool autosizeColumnWidth(int column);
|
||||
bool autosizeColumnWidth(int colFirst, int colLast);
|
||||
bool autosizeColumnWidth();
|
||||
|
||||
private:
|
||||
QMap<int, int> getMaximalColumnWidth(int firstRow = 1, int lastRow = INT_MAX);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Document) // Disables the use of copy constructors and
|
||||
// assignment operators for the given Class.
|
||||
DocumentPrivate *const d_ptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_XLSXDOCUMENT_H
|
|
@ -0,0 +1,42 @@
|
|||
// xlsxdocument_p.h
|
||||
|
||||
#ifndef XLSXDOCUMENT_P_H
|
||||
#define XLSXDOCUMENT_P_H
|
||||
|
||||
#include "xlsxcontenttypes_p.h"
|
||||
#include "xlsxdocument.h"
|
||||
#include "xlsxglobal.h"
|
||||
#include "xlsxworkbook.h"
|
||||
|
||||
#include <QMap>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class DocumentPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(Document)
|
||||
public:
|
||||
DocumentPrivate(Document *p);
|
||||
void init();
|
||||
|
||||
bool loadPackage(QIODevice *device);
|
||||
bool savePackage(QIODevice *device) const;
|
||||
|
||||
bool saveCsv(const QString mainCSVFileName) const;
|
||||
|
||||
// copy style from one xlsx file to other
|
||||
static bool copyStyle(const QString &from, const QString &to);
|
||||
|
||||
Document *q_ptr;
|
||||
const QString defaultPackageName; // default name when package name not specified
|
||||
QString packageName; // name of the .xlsx file
|
||||
|
||||
QMap<QString, QString> documentProperties; // core, app and custom properties
|
||||
std::shared_ptr<Workbook> workbook;
|
||||
std::shared_ptr<ContentTypes> contentTypes;
|
||||
bool isLoad;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXDOCUMENT_P_H
|
|
@ -0,0 +1,37 @@
|
|||
// xlsxdrwaing_p.h
|
||||
|
||||
#ifndef QXLSX_DRAWING_H
|
||||
#define QXLSX_DRAWING_H
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
#include "xlsxrelationships_p.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
class QIODevice;
|
||||
class QXmlStreamWriter;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class DrawingAnchor;
|
||||
class Workbook;
|
||||
class AbstractSheet;
|
||||
class MediaFile;
|
||||
|
||||
class Drawing : public AbstractOOXmlFile
|
||||
{
|
||||
public:
|
||||
Drawing(AbstractSheet *sheet, CreateFlag flag);
|
||||
~Drawing();
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
|
||||
AbstractSheet *sheet;
|
||||
Workbook *workbook;
|
||||
QList<DrawingAnchor *> anchors;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_DRAWING_H
|
|
@ -0,0 +1,162 @@
|
|||
// xlsxdrawinganchor_p.h
|
||||
|
||||
#ifndef QXLSX_XLSXDRAWINGANCHOR_P_H
|
||||
#define QXLSX_XLSXDRAWINGANCHOR_P_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QPoint>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Drawing;
|
||||
class MediaFile;
|
||||
class Chart;
|
||||
|
||||
// Helper class
|
||||
struct XlsxMarker {
|
||||
XlsxMarker() {}
|
||||
XlsxMarker(int row, int column, int rowOffset, int colOffset)
|
||||
: cell(QPoint(row, column))
|
||||
, offset(rowOffset, colOffset)
|
||||
{
|
||||
}
|
||||
|
||||
int row() const { return cell.x(); }
|
||||
int col() const { return cell.y(); }
|
||||
int rowOff() const { return offset.width(); }
|
||||
int colOff() const { return offset.height(); }
|
||||
|
||||
QPoint cell;
|
||||
QSize offset;
|
||||
};
|
||||
|
||||
class DrawingAnchor
|
||||
{
|
||||
public:
|
||||
enum ObjectType { GraphicFrame, Shape, GroupShape, ConnectionShape, Picture, Unknown };
|
||||
|
||||
DrawingAnchor(Drawing *drawing, ObjectType objectType);
|
||||
virtual ~DrawingAnchor();
|
||||
|
||||
void setObjectPicture(const QImage &img);
|
||||
bool getObjectPicture(QImage &img);
|
||||
|
||||
void setObjectGraphicFrame(std::shared_ptr<QXlsx::Chart> chart);
|
||||
|
||||
virtual bool loadFromXml(QXmlStreamReader &reader) = 0;
|
||||
virtual void saveToXml(QXmlStreamWriter &writer) const = 0;
|
||||
|
||||
virtual int row() const;
|
||||
virtual int col() const;
|
||||
|
||||
protected:
|
||||
QPoint loadXmlPos(QXmlStreamReader &reader);
|
||||
QSize loadXmlExt(QXmlStreamReader &reader);
|
||||
XlsxMarker loadXmlMarker(QXmlStreamReader &reader, const QString &node);
|
||||
void loadXmlObject(QXmlStreamReader &reader);
|
||||
void loadXmlObjectShape(QXmlStreamReader &reader);
|
||||
void loadXmlObjectGroupShape(QXmlStreamReader &reader);
|
||||
void loadXmlObjectGraphicFrame(QXmlStreamReader &reader);
|
||||
void loadXmlObjectConnectionShape(QXmlStreamReader &reader);
|
||||
void loadXmlObjectPicture(QXmlStreamReader &reader);
|
||||
|
||||
void saveXmlPos(QXmlStreamWriter &writer, const QPoint &pos) const;
|
||||
void saveXmlExt(QXmlStreamWriter &writer, const QSize &ext) const;
|
||||
void saveXmlMarker(QXmlStreamWriter &writer,
|
||||
const XlsxMarker &marker,
|
||||
const QString &node) const;
|
||||
void saveXmlObject(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectShape(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectGroupShape(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectConnectionShape(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectPicture(QXmlStreamWriter &writer) const;
|
||||
|
||||
Drawing *m_drawing;
|
||||
ObjectType m_objectType;
|
||||
std::shared_ptr<MediaFile> m_pictureFile;
|
||||
std::shared_ptr<Chart> m_chartFile;
|
||||
|
||||
int m_id;
|
||||
|
||||
public:
|
||||
int getm_id();
|
||||
|
||||
protected:
|
||||
// liufeij {{
|
||||
void setObjectShape(const QImage &img); // liufeij
|
||||
|
||||
QString editASName;
|
||||
// below only for twocellanchor shape
|
||||
QPoint posTA; // for shape liufeij 20181024
|
||||
QSize extTA; // for shape liufeij 20181024
|
||||
int rotWithShapeTA; //// for shape liufeij 20181024
|
||||
int dpiTA; //// for shape liufeij 20181024
|
||||
QString sp_textlink, sp_macro, sp_blip_cstate, sp_blip_rembed;
|
||||
|
||||
// BELOW only for cxnSp shape
|
||||
QString cxnSp_filpV, cxnSp_macro;
|
||||
// below for cxnsp and sp
|
||||
QString xsp_cNvPR_name, xsp_cNvPR_id; // x measns shape and cxnSp together using
|
||||
QString xbwMode; // same as above
|
||||
QString xIn_algn, xIn_cmpd, xIn_cap, xIn_w; // cxnSp only need xIn_w
|
||||
QString xprstGeom_prst;
|
||||
QString x_headEnd_w, x_headEnd_len, x_headEnd_tyep;
|
||||
QString x_tailEnd_w, x_tailEnd_len, x_tailEnd_tyep;
|
||||
QString Style_inref_idx, style_fillref_idx, style_effectref_idx, style_forntref_idx;
|
||||
QString Style_inref_val, style_fillref_val, style_effectref_val, style_forntref_val;
|
||||
// liufeij }}
|
||||
};
|
||||
|
||||
class DrawingAbsoluteAnchor : public DrawingAnchor
|
||||
{
|
||||
public:
|
||||
DrawingAbsoluteAnchor(Drawing *drawing, ObjectType objectType = Unknown);
|
||||
|
||||
QPoint pos;
|
||||
QSize ext;
|
||||
|
||||
bool loadFromXml(QXmlStreamReader &reader) override;
|
||||
void saveToXml(QXmlStreamWriter &writer) const override;
|
||||
};
|
||||
|
||||
class DrawingOneCellAnchor : public DrawingAnchor
|
||||
{
|
||||
public:
|
||||
DrawingOneCellAnchor(Drawing *drawing, ObjectType objectType = Unknown);
|
||||
|
||||
XlsxMarker from;
|
||||
QSize ext;
|
||||
|
||||
int row() const override;
|
||||
int col() const override;
|
||||
|
||||
bool loadFromXml(QXmlStreamReader &reader) override;
|
||||
void saveToXml(QXmlStreamWriter &writer) const override;
|
||||
};
|
||||
|
||||
class DrawingTwoCellAnchor : public DrawingAnchor
|
||||
{
|
||||
public:
|
||||
DrawingTwoCellAnchor(Drawing *drawing, ObjectType objectType = Unknown);
|
||||
|
||||
XlsxMarker from;
|
||||
XlsxMarker to;
|
||||
|
||||
int row() const override;
|
||||
int col() const override;
|
||||
|
||||
bool loadFromXml(QXmlStreamReader &reader) override;
|
||||
void saveToXml(QXmlStreamWriter &writer) const override;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_XLSXDRAWINGANCHOR_P_H
|
|
@ -0,0 +1,255 @@
|
|||
// xlsxformat.h
|
||||
|
||||
#ifndef QXLSX_FORMAT_H
|
||||
#define QXLSX_FORMAT_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QColor>
|
||||
#include <QExplicitlySharedDataPointer>
|
||||
#include <QFont>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
|
||||
class FormatTest;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Styles;
|
||||
class Worksheet;
|
||||
class WorksheetPrivate;
|
||||
class RichStringPrivate;
|
||||
class SharedStrings;
|
||||
|
||||
class FormatPrivate;
|
||||
|
||||
class QXLSX_EXPORT Format
|
||||
{
|
||||
public:
|
||||
enum FontScript { FontScriptNormal, FontScriptSuper, FontScriptSub };
|
||||
|
||||
enum FontUnderline {
|
||||
FontUnderlineNone,
|
||||
FontUnderlineSingle,
|
||||
FontUnderlineDouble,
|
||||
FontUnderlineSingleAccounting,
|
||||
FontUnderlineDoubleAccounting
|
||||
};
|
||||
|
||||
enum HorizontalAlignment {
|
||||
AlignHGeneral,
|
||||
AlignLeft,
|
||||
AlignHCenter,
|
||||
AlignRight,
|
||||
AlignHFill,
|
||||
AlignHJustify,
|
||||
AlignHMerge,
|
||||
AlignHDistributed
|
||||
};
|
||||
|
||||
enum VerticalAlignment {
|
||||
AlignTop,
|
||||
AlignVCenter,
|
||||
AlignBottom,
|
||||
AlignVJustify,
|
||||
AlignVDistributed
|
||||
};
|
||||
|
||||
enum BorderStyle {
|
||||
BorderNone,
|
||||
BorderThin,
|
||||
BorderMedium,
|
||||
BorderDashed,
|
||||
BorderDotted,
|
||||
BorderThick,
|
||||
BorderDouble,
|
||||
BorderHair,
|
||||
BorderMediumDashed,
|
||||
BorderDashDot,
|
||||
BorderMediumDashDot,
|
||||
BorderDashDotDot,
|
||||
BorderMediumDashDotDot,
|
||||
BorderSlantDashDot
|
||||
};
|
||||
|
||||
enum DiagonalBorderType {
|
||||
DiagonalBorderNone,
|
||||
DiagonalBorderDown,
|
||||
DiagonalBorderUp,
|
||||
DiagnoalBorderBoth
|
||||
};
|
||||
|
||||
enum FillPattern {
|
||||
PatternNone,
|
||||
PatternSolid,
|
||||
PatternMediumGray,
|
||||
PatternDarkGray,
|
||||
PatternLightGray,
|
||||
PatternDarkHorizontal,
|
||||
PatternDarkVertical,
|
||||
PatternDarkDown,
|
||||
PatternDarkUp,
|
||||
PatternDarkGrid,
|
||||
PatternDarkTrellis,
|
||||
PatternLightHorizontal,
|
||||
PatternLightVertical,
|
||||
PatternLightDown,
|
||||
PatternLightUp,
|
||||
PatternLightTrellis,
|
||||
PatternGray125,
|
||||
PatternGray0625,
|
||||
PatternLightGrid
|
||||
};
|
||||
|
||||
Format();
|
||||
Format(const Format &other);
|
||||
Format &operator=(const Format &rhs);
|
||||
~Format();
|
||||
|
||||
int numberFormatIndex() const;
|
||||
void setNumberFormatIndex(int format);
|
||||
QString numberFormat() const;
|
||||
void setNumberFormat(const QString &format);
|
||||
void setNumberFormat(int id, const QString &format);
|
||||
bool isDateTimeFormat() const;
|
||||
|
||||
int fontSize() const;
|
||||
void setFontSize(int size);
|
||||
bool fontItalic() const;
|
||||
void setFontItalic(bool italic);
|
||||
bool fontStrikeOut() const;
|
||||
void setFontStrikeOut(bool);
|
||||
QColor fontColor() const;
|
||||
void setFontColor(const QColor &);
|
||||
bool fontBold() const;
|
||||
void setFontBold(bool bold);
|
||||
FontScript fontScript() const;
|
||||
void setFontScript(FontScript);
|
||||
FontUnderline fontUnderline() const;
|
||||
void setFontUnderline(FontUnderline);
|
||||
bool fontOutline() const;
|
||||
void setFontOutline(bool outline);
|
||||
QString fontName() const;
|
||||
void setFontName(const QString &);
|
||||
QFont font() const;
|
||||
void setFont(const QFont &font);
|
||||
|
||||
HorizontalAlignment horizontalAlignment() const;
|
||||
void setHorizontalAlignment(HorizontalAlignment align);
|
||||
VerticalAlignment verticalAlignment() const;
|
||||
void setVerticalAlignment(VerticalAlignment align);
|
||||
bool textWrap() const;
|
||||
void setTextWrap(bool textWrap);
|
||||
int rotation() const;
|
||||
void setRotation(int rotation);
|
||||
int indent() const;
|
||||
void setIndent(int indent);
|
||||
bool shrinkToFit() const;
|
||||
void setShrinkToFit(bool shink);
|
||||
|
||||
void setBorderStyle(BorderStyle style);
|
||||
void setBorderColor(const QColor &color);
|
||||
BorderStyle leftBorderStyle() const;
|
||||
void setLeftBorderStyle(BorderStyle style);
|
||||
QColor leftBorderColor() const;
|
||||
void setLeftBorderColor(const QColor &color);
|
||||
BorderStyle rightBorderStyle() const;
|
||||
void setRightBorderStyle(BorderStyle style);
|
||||
QColor rightBorderColor() const;
|
||||
void setRightBorderColor(const QColor &color);
|
||||
BorderStyle topBorderStyle() const;
|
||||
void setTopBorderStyle(BorderStyle style);
|
||||
QColor topBorderColor() const;
|
||||
void setTopBorderColor(const QColor &color);
|
||||
BorderStyle bottomBorderStyle() const;
|
||||
void setBottomBorderStyle(BorderStyle style);
|
||||
QColor bottomBorderColor() const;
|
||||
void setBottomBorderColor(const QColor &color);
|
||||
BorderStyle diagonalBorderStyle() const;
|
||||
void setDiagonalBorderStyle(BorderStyle style);
|
||||
DiagonalBorderType diagonalBorderType() const;
|
||||
void setDiagonalBorderType(DiagonalBorderType style);
|
||||
QColor diagonalBorderColor() const;
|
||||
void setDiagonalBorderColor(const QColor &color);
|
||||
|
||||
FillPattern fillPattern() const;
|
||||
void setFillPattern(FillPattern pattern);
|
||||
QColor patternForegroundColor() const;
|
||||
void setPatternForegroundColor(const QColor &color);
|
||||
QColor patternBackgroundColor() const;
|
||||
void setPatternBackgroundColor(const QColor &color);
|
||||
|
||||
bool locked() const;
|
||||
void setLocked(bool locked);
|
||||
bool hidden() const;
|
||||
void setHidden(bool hidden);
|
||||
|
||||
void mergeFormat(const Format &modifier);
|
||||
bool isValid() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
bool operator==(const Format &format) const;
|
||||
bool operator!=(const Format &format) const;
|
||||
|
||||
QVariant property(int propertyId, const QVariant &defaultValue = QVariant()) const;
|
||||
void setProperty(int propertyId,
|
||||
const QVariant &value,
|
||||
const QVariant &clearValue = QVariant(),
|
||||
bool detach = true);
|
||||
void clearProperty(int propertyId);
|
||||
bool hasProperty(int propertyId) const;
|
||||
|
||||
bool boolProperty(int propertyId, bool defaultValue = false) const;
|
||||
int intProperty(int propertyId, int defaultValue = 0) const;
|
||||
double doubleProperty(int propertyId, double defaultValue = 0.0) const;
|
||||
QString stringProperty(int propertyId, const QString &defaultValue = QString()) const;
|
||||
QColor colorProperty(int propertyId, const QColor &defaultValue = QColor()) const;
|
||||
|
||||
bool hasNumFmtData() const;
|
||||
bool hasFontData() const;
|
||||
bool hasFillData() const;
|
||||
bool hasBorderData() const;
|
||||
bool hasAlignmentData() const;
|
||||
bool hasProtectionData() const;
|
||||
|
||||
bool fontIndexValid() const;
|
||||
int fontIndex() const;
|
||||
QByteArray fontKey() const;
|
||||
bool borderIndexValid() const;
|
||||
QByteArray borderKey() const;
|
||||
int borderIndex() const;
|
||||
bool fillIndexValid() const;
|
||||
QByteArray fillKey() const;
|
||||
int fillIndex() const;
|
||||
|
||||
QByteArray formatKey() const;
|
||||
bool xfIndexValid() const;
|
||||
int xfIndex() const;
|
||||
bool dxfIndexValid() const;
|
||||
int dxfIndex() const;
|
||||
|
||||
void fixNumberFormat(int id, const QString &format);
|
||||
void setFontIndex(int index);
|
||||
void setBorderIndex(int index);
|
||||
void setFillIndex(int index);
|
||||
void setXfIndex(int index);
|
||||
void setDxfIndex(int index);
|
||||
|
||||
private:
|
||||
friend class Styles;
|
||||
friend class ::FormatTest;
|
||||
friend QDebug operator<<(QDebug, const Format &f);
|
||||
|
||||
int theme() const;
|
||||
|
||||
QExplicitlySharedDataPointer<FormatPrivate> d;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
QDebug operator<<(QDebug dbg, const Format &f);
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_FORMAT_H
|
|
@ -0,0 +1,127 @@
|
|||
// xlsxformat_p.h
|
||||
#ifndef XLSXFORMAT_P_H
|
||||
#define XLSXFORMAT_P_H
|
||||
|
||||
#include "xlsxformat.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QSharedData>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class FormatPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
enum FormatType {
|
||||
FT_Invalid = 0,
|
||||
FT_NumFmt = 0x01,
|
||||
FT_Font = 0x02,
|
||||
FT_Alignment = 0x04,
|
||||
FT_Border = 0x08,
|
||||
FT_Fill = 0x10,
|
||||
FT_Protection = 0x20
|
||||
};
|
||||
|
||||
enum Property {
|
||||
P_STARTID,
|
||||
|
||||
// numFmt
|
||||
P_NumFmt_Id,
|
||||
P_NumFmt_FormatCode,
|
||||
|
||||
// font
|
||||
P_Font_STARTID,
|
||||
P_Font_Size = P_Font_STARTID,
|
||||
P_Font_Italic,
|
||||
P_Font_StrikeOut,
|
||||
P_Font_Color,
|
||||
P_Font_Bold,
|
||||
P_Font_Script,
|
||||
P_Font_Underline,
|
||||
P_Font_Outline,
|
||||
P_Font_Shadow,
|
||||
P_Font_Name,
|
||||
P_Font_Family,
|
||||
P_Font_Charset,
|
||||
P_Font_Scheme,
|
||||
P_Font_Condense,
|
||||
P_Font_Extend,
|
||||
P_Font_ENDID,
|
||||
|
||||
// border
|
||||
P_Border_STARTID,
|
||||
P_Border_LeftStyle = P_Border_STARTID,
|
||||
P_Border_RightStyle,
|
||||
P_Border_TopStyle,
|
||||
P_Border_BottomStyle,
|
||||
P_Border_DiagonalStyle,
|
||||
P_Border_LeftColor,
|
||||
P_Border_RightColor,
|
||||
P_Border_TopColor,
|
||||
P_Border_BottomColor,
|
||||
P_Border_DiagonalColor,
|
||||
P_Border_DiagonalType,
|
||||
P_Border_ENDID,
|
||||
|
||||
// fill
|
||||
P_Fill_STARTID,
|
||||
P_Fill_Pattern = P_Fill_STARTID,
|
||||
P_Fill_BgColor,
|
||||
P_Fill_FgColor,
|
||||
P_Fill_ENDID,
|
||||
|
||||
// alignment
|
||||
P_Alignment_STARTID,
|
||||
P_Alignment_AlignH = P_Alignment_STARTID,
|
||||
P_Alignment_AlignV,
|
||||
P_Alignment_Wrap,
|
||||
P_Alignment_Rotation,
|
||||
P_Alignment_Indent,
|
||||
P_Alignment_ShinkToFit,
|
||||
P_Alignment_ENDID,
|
||||
|
||||
// protection
|
||||
P_Protection_Locked,
|
||||
P_Protection_Hidden,
|
||||
|
||||
P_ENDID
|
||||
};
|
||||
|
||||
FormatPrivate();
|
||||
FormatPrivate(const FormatPrivate &other);
|
||||
~FormatPrivate();
|
||||
|
||||
bool dirty; // The key re-generation is need.
|
||||
QByteArray formatKey;
|
||||
|
||||
bool font_dirty;
|
||||
bool font_index_valid;
|
||||
QByteArray font_key;
|
||||
int font_index;
|
||||
|
||||
bool fill_dirty;
|
||||
bool fill_index_valid;
|
||||
QByteArray fill_key;
|
||||
int fill_index;
|
||||
|
||||
bool border_dirty;
|
||||
bool border_index_valid;
|
||||
QByteArray border_key;
|
||||
int border_index;
|
||||
|
||||
int xf_index;
|
||||
bool xf_indexValid;
|
||||
|
||||
bool is_dxf_fomat;
|
||||
int dxf_index;
|
||||
bool dxf_indexValid;
|
||||
|
||||
int theme;
|
||||
|
||||
QMap<int, QVariant> properties;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
// xlsxglobal.h
|
||||
|
||||
#ifndef XLSXGLOBAL_H
|
||||
#define XLSXGLOBAL_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QIODevice>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
#if defined(QXlsx_SHAREDLIB)
|
||||
# if defined(QXlsx_EXPORTS)
|
||||
# define QXLSX_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QXLSX_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QXLSX_EXPORT
|
||||
#endif
|
||||
|
||||
#define QT_BEGIN_NAMESPACE_XLSX namespace QXlsx {
|
||||
#define QT_END_NAMESPACE_XLSX }
|
||||
|
||||
#define QXLSX_USE_NAMESPACE using namespace QXlsx;
|
||||
|
||||
#endif // XLSXGLOBAL_H
|
|
@ -0,0 +1,46 @@
|
|||
// xlsxmediafile_p.h
|
||||
|
||||
#ifndef QXLSX_XLSXMEDIAFILE_H
|
||||
#define QXLSX_XLSXMEDIAFILE_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class MediaFile
|
||||
{
|
||||
public:
|
||||
MediaFile(const QString &fileName);
|
||||
MediaFile(const QByteArray &bytes, const QString &suffix, const QString &mimeType = QString());
|
||||
|
||||
public:
|
||||
void set(const QByteArray &bytes, const QString &suffix, const QString &mimeType = QString());
|
||||
QString suffix() const;
|
||||
QString mimeType() const;
|
||||
QByteArray contents() const;
|
||||
|
||||
bool isIndexValid() const;
|
||||
int index() const;
|
||||
void setIndex(int idx);
|
||||
QByteArray hashKey() const;
|
||||
|
||||
void setFileName(const QString &name);
|
||||
QString fileName() const;
|
||||
|
||||
protected:
|
||||
QString m_fileName;
|
||||
QByteArray m_contents;
|
||||
QString m_suffix;
|
||||
QString m_mimeType;
|
||||
|
||||
int m_index;
|
||||
bool m_indexValid;
|
||||
QByteArray m_hashKey;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_XLSXMEDIAFILE_H
|
|
@ -0,0 +1,51 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** All right reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QXLSX_NUMFORMATPARSER_H
|
||||
#define QXLSX_NUMFORMATPARSER_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt Xlsx API. It exists for the convenience
|
||||
// of the Qt Xlsx. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class NumFormatParser
|
||||
{
|
||||
public:
|
||||
static bool isDateTime(const QString &formatCode);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_NUMFORMATPARSER_H
|
|
@ -0,0 +1,92 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** All right reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef XLSXRELATIONSHIPS_H
|
||||
#define XLSXRELATIONSHIPS_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt Xlsx API. It exists for the convenience
|
||||
// of the Qt Xlsx. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
struct XlsxRelationship {
|
||||
QString id;
|
||||
QString type;
|
||||
QString target;
|
||||
QString targetMode;
|
||||
};
|
||||
|
||||
class Relationships
|
||||
{
|
||||
public:
|
||||
Relationships();
|
||||
|
||||
QList<XlsxRelationship> documentRelationships(const QString &relativeType) const;
|
||||
QList<XlsxRelationship> packageRelationships(const QString &relativeType) const;
|
||||
QList<XlsxRelationship> msPackageRelationships(const QString &relativeType) const;
|
||||
QList<XlsxRelationship> worksheetRelationships(const QString &relativeType) const;
|
||||
|
||||
void addDocumentRelationship(const QString &relativeType, const QString &target);
|
||||
void addPackageRelationship(const QString &relativeType, const QString &target);
|
||||
void addMsPackageRelationship(const QString &relativeType, const QString &target);
|
||||
void addWorksheetRelationship(const QString &relativeType,
|
||||
const QString &target,
|
||||
const QString &targetMode = QString());
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const;
|
||||
QByteArray saveToXmlData() const;
|
||||
bool loadFromXmlFile(QIODevice *device);
|
||||
bool loadFromXmlData(const QByteArray &data);
|
||||
XlsxRelationship getRelationshipById(const QString &id) const;
|
||||
|
||||
void clear();
|
||||
int count() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
private:
|
||||
QList<XlsxRelationship> relationships(const QString &type) const;
|
||||
void addRelationship(const QString &type,
|
||||
const QString &target,
|
||||
const QString &targetMode = QString());
|
||||
|
||||
QList<XlsxRelationship> m_relationships;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXRELATIONSHIPS_H
|
|
@ -0,0 +1,91 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** All right reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef XLSXRICHSTRING_H
|
||||
#define XLSXRICHSTRING_H
|
||||
|
||||
#include "xlsxformat.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QSharedDataPointer>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
class RichStringPrivate;
|
||||
class RichString;
|
||||
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
|
||||
uint qHash(const RichString &rs, uint seed = 0) Q_DECL_NOTHROW;
|
||||
|
||||
class QXLSX_EXPORT RichString
|
||||
{
|
||||
public:
|
||||
RichString();
|
||||
explicit RichString(const QString &text);
|
||||
RichString(const RichString &other);
|
||||
~RichString();
|
||||
|
||||
bool isRichString() const;
|
||||
bool isNull() const;
|
||||
bool isEmtpy() const;
|
||||
QString toPlainString() const;
|
||||
QString toHtml() const;
|
||||
void setHtml(const QString &text);
|
||||
|
||||
int fragmentCount() const;
|
||||
void addFragment(const QString &text, const Format &format);
|
||||
QString fragmentText(int index) const;
|
||||
Format fragmentFormat(int index) const;
|
||||
|
||||
operator QVariant() const;
|
||||
|
||||
RichString &operator=(const RichString &other);
|
||||
|
||||
private:
|
||||
friend uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW;
|
||||
friend bool operator==(const RichString &rs1, const RichString &rs2);
|
||||
friend bool operator!=(const RichString &rs1, const RichString &rs2);
|
||||
friend bool operator<(const RichString &rs1, const RichString &rs2);
|
||||
friend QDebug operator<<(QDebug dbg, const RichString &rs);
|
||||
|
||||
QSharedDataPointer<RichStringPrivate> d;
|
||||
};
|
||||
|
||||
bool operator==(const RichString &rs1, const RichString &rs2);
|
||||
bool operator!=(const RichString &rs1, const RichString &rs2);
|
||||
bool operator<(const RichString &rs1, const RichString &rs2);
|
||||
bool operator==(const RichString &rs1, const QString &rs2);
|
||||
bool operator==(const QString &rs1, const RichString &rs2);
|
||||
bool operator!=(const RichString &rs1, const QString &rs2);
|
||||
bool operator!=(const QString &rs1, const RichString &rs2);
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
QDebug operator<<(QDebug dbg, const RichString &rs);
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
Q_DECLARE_METATYPE(QXlsx::RichString)
|
||||
|
||||
#endif // XLSXRICHSTRING_H
|
|
@ -0,0 +1,60 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** All right reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef XLSXRICHSTRING_P_H
|
||||
#define XLSXRICHSTRING_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt Xlsx API. It exists for the convenience
|
||||
// of the Qt Xlsx. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "xlsxrichstring.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class RichStringPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
RichStringPrivate();
|
||||
RichStringPrivate(const RichStringPrivate &other);
|
||||
~RichStringPrivate();
|
||||
|
||||
QByteArray idKey() const;
|
||||
|
||||
QStringList fragmentTexts;
|
||||
QList<Format> fragmentFormats;
|
||||
QByteArray _idKey;
|
||||
bool _dirty;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXRICHSTRING_P_H
|
|
@ -0,0 +1,99 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** All right reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef XLSXSHAREDSTRINGS_H
|
||||
#define XLSXSHAREDSTRINGS_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt Xlsx API. It exists for the convenience
|
||||
// of the Qt Xlsx. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
#include "xlsxglobal.h"
|
||||
#include "xlsxrichstring.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QIODevice>
|
||||
#include <QStringList>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class XlsxSharedStringInfo
|
||||
{
|
||||
public:
|
||||
XlsxSharedStringInfo(int index = 0, int count = 1)
|
||||
: index(index)
|
||||
, count(count)
|
||||
{
|
||||
}
|
||||
|
||||
int index;
|
||||
int count;
|
||||
};
|
||||
|
||||
class SharedStrings : public AbstractOOXmlFile
|
||||
{
|
||||
public:
|
||||
SharedStrings(CreateFlag flag);
|
||||
int count() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
int addSharedString(const QString &string);
|
||||
int addSharedString(const RichString &string);
|
||||
void removeSharedString(const QString &string);
|
||||
void removeSharedString(const RichString &string);
|
||||
void incRefByStringIndex(int idx);
|
||||
|
||||
int getSharedStringIndex(const QString &string) const;
|
||||
int getSharedStringIndex(const RichString &string) const;
|
||||
RichString getSharedString(int index) const;
|
||||
QList<RichString> getSharedStrings() const;
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
|
||||
private:
|
||||
void readString(QXmlStreamReader &reader); // <si>
|
||||
void readRichStringPart(QXmlStreamReader &reader, RichString &rich); // <r>
|
||||
void readPlainStringPart(QXmlStreamReader &reader, RichString &rich); // <v>
|
||||
Format readRichStringPart_rPr(QXmlStreamReader &reader);
|
||||
void writeRichStringPart_rPr(QXmlStreamWriter &writer, const Format &format) const;
|
||||
|
||||
QHash<RichString, XlsxSharedStringInfo> m_stringTable; // for fast lookup
|
||||
QList<RichString> m_stringList;
|
||||
int m_stringCount;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXSHAREDSTRINGS_H
|
|
@ -0,0 +1,60 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** All right reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef XLSXSIMPLEOOXMLFILE_H
|
||||
#define XLSXSIMPLEOOXMLFILE_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt Xlsx API. It exists for the convenience
|
||||
// of the Qt Xlsx. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class SimpleOOXmlFile : public AbstractOOXmlFile
|
||||
{
|
||||
public:
|
||||
SimpleOOXmlFile(CreateFlag flag);
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
QByteArray saveToXmlData() const override;
|
||||
bool loadFromXmlData(const QByteArray &data) override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
|
||||
QByteArray xmlData;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXSIMPLEOOXMLFILE_H
|
|
@ -0,0 +1,152 @@
|
|||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** All right reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef XLSXSTYLES_H
|
||||
#define XLSXSTYLES_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt Xlsx API. It exists for the convenience
|
||||
// of the Qt Xlsx. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QHash>
|
||||
#include <QIODevice>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
// class StylesTest;
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
#include "xlsxformat.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Format;
|
||||
class XlsxColor;
|
||||
|
||||
struct XlsxFormatNumberData {
|
||||
XlsxFormatNumberData()
|
||||
: formatIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
int formatIndex;
|
||||
QString formatString;
|
||||
};
|
||||
|
||||
class Styles : public AbstractOOXmlFile
|
||||
{
|
||||
public:
|
||||
Styles(CreateFlag flag);
|
||||
~Styles();
|
||||
void addXfFormat(const Format &format, bool force = false);
|
||||
Format xfFormat(int idx) const;
|
||||
void addDxfFormat(const Format &format, bool force = false);
|
||||
Format dxfFormat(int idx) const;
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
|
||||
QColor getColorByIndex(int idx);
|
||||
|
||||
private:
|
||||
friend class Format;
|
||||
// friend class ::StylesTest;
|
||||
|
||||
void fixNumFmt(const Format &format);
|
||||
|
||||
void writeNumFmts(QXmlStreamWriter &writer) const;
|
||||
void writeFonts(QXmlStreamWriter &writer) const;
|
||||
void writeFont(QXmlStreamWriter &writer, const Format &font, bool isDxf = false) const;
|
||||
void writeFills(QXmlStreamWriter &writer) const;
|
||||
void writeFill(QXmlStreamWriter &writer, const Format &fill, bool isDxf = false) const;
|
||||
void writeBorders(QXmlStreamWriter &writer) const;
|
||||
void writeBorder(QXmlStreamWriter &writer, const Format &border, bool isDxf = false) const;
|
||||
void writeSubBorder(QXmlStreamWriter &writer,
|
||||
const QString &type,
|
||||
int style,
|
||||
const XlsxColor &color) const;
|
||||
void writeCellXfs(QXmlStreamWriter &writer) const;
|
||||
void writeDxfs(QXmlStreamWriter &writer) const;
|
||||
void writeDxf(QXmlStreamWriter &writer, const Format &format) const;
|
||||
void writeColors(QXmlStreamWriter &writer) const;
|
||||
|
||||
bool readNumFmts(QXmlStreamReader &reader);
|
||||
bool readFonts(QXmlStreamReader &reader);
|
||||
bool readFont(QXmlStreamReader &reader, Format &format);
|
||||
bool readFills(QXmlStreamReader &reader);
|
||||
bool readFill(QXmlStreamReader &reader, Format &format);
|
||||
bool readBorders(QXmlStreamReader &reader);
|
||||
bool readBorder(QXmlStreamReader &reader, Format &format);
|
||||
bool readSubBorder(QXmlStreamReader &reader,
|
||||
const QString &name,
|
||||
Format::BorderStyle &style,
|
||||
XlsxColor &color);
|
||||
bool readCellXfs(QXmlStreamReader &reader);
|
||||
bool readDxfs(QXmlStreamReader &reader);
|
||||
bool readDxf(QXmlStreamReader &reader);
|
||||
bool readColors(QXmlStreamReader &reader);
|
||||
bool readIndexedColors(QXmlStreamReader &reader);
|
||||
|
||||
bool readCellStyleXfs(QXmlStreamReader &reader);
|
||||
|
||||
QHash<QString, int> m_builtinNumFmtsHash;
|
||||
QMap<int, std::shared_ptr<XlsxFormatNumberData>> m_customNumFmtIdMap;
|
||||
QHash<QString, std::shared_ptr<XlsxFormatNumberData>> m_customNumFmtsHash;
|
||||
int m_nextCustomNumFmtId;
|
||||
QList<Format> m_fontsList;
|
||||
QList<Format> m_fillsList;
|
||||
QList<Format> m_bordersList;
|
||||
QHash<QByteArray, Format> m_fontsHash;
|
||||
QHash<QByteArray, Format> m_fillsHash;
|
||||
QHash<QByteArray, Format> m_bordersHash;
|
||||
|
||||
QVector<QColor> m_indexedColors;
|
||||
bool m_isIndexedColorsDefault;
|
||||
|
||||
QList<Format> m_xf_formatsList;
|
||||
QHash<QByteArray, Format> m_xf_formatsHash;
|
||||
|
||||
QList<Format> m_dxf_formatsList;
|
||||
QHash<QByteArray, Format> m_dxf_formatsHash;
|
||||
|
||||
bool m_emptyFormatAdded;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXSTYLES_H
|
|
@ -0,0 +1,28 @@
|
|||
// xlsxtheme_p.h
|
||||
|
||||
#ifndef XLSXTHEME_H
|
||||
#define XLSXTHEME_H
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class Theme : public AbstractOOXmlFile
|
||||
{
|
||||
public:
|
||||
Theme(CreateFlag flag);
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
QByteArray saveToXmlData() const override;
|
||||
bool loadFromXmlData(const QByteArray &data) override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
|
||||
QByteArray xmlData;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXTHEME_H
|
|
@ -0,0 +1,43 @@
|
|||
// xlsxutility_p.h
|
||||
|
||||
#ifndef XLSXUTILITY_H
|
||||
#define XLSXUTILITY_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTime>
|
||||
#include <QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class CellReference;
|
||||
|
||||
bool parseXsdBoolean(const QString &value, bool defaultValue = false);
|
||||
QString xsdBoolean(bool value);
|
||||
|
||||
QStringList splitPath(const QString &path);
|
||||
QString getRelFilePath(const QString &filePath);
|
||||
|
||||
double datetimeToNumber(const QDateTime &dt, bool is1904 = false);
|
||||
QVariant datetimeFromNumber(double num, bool is1904 = false);
|
||||
double timeToNumber(const QTime &t);
|
||||
|
||||
QString createSafeSheetName(const QString &nameProposal);
|
||||
QString escapeSheetName(const QString &sheetName);
|
||||
QString unescapeSheetName(const QString &sheetName);
|
||||
|
||||
bool isSpaceReserveNeeded(const QString &string);
|
||||
|
||||
QString convertSharedFormula(const QString &rootFormula,
|
||||
const CellReference &rootCell,
|
||||
const CellReference &cell);
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif // XLSXUTILITY_H
|
|
@ -0,0 +1,101 @@
|
|||
// xlsxworkbook.h
|
||||
|
||||
#ifndef XLSXWORKBOOK_H
|
||||
#define XLSXWORKBOOK_H
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
#include "xlsxabstractsheet.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QImage>
|
||||
#include <QList>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class SharedStrings;
|
||||
class Styles;
|
||||
class Drawing;
|
||||
class Document;
|
||||
class Theme;
|
||||
class Relationships;
|
||||
class DocumentPrivate;
|
||||
class MediaFile;
|
||||
class Chart;
|
||||
class Chartsheet;
|
||||
class Worksheet;
|
||||
class WorkbookPrivate;
|
||||
|
||||
class QXLSX_EXPORT Workbook : public AbstractOOXmlFile
|
||||
{
|
||||
Q_DECLARE_PRIVATE(Workbook)
|
||||
public:
|
||||
~Workbook();
|
||||
|
||||
int sheetCount() const;
|
||||
AbstractSheet *sheet(int index) const;
|
||||
|
||||
AbstractSheet *addSheet(const QString &name = QString(),
|
||||
AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet);
|
||||
AbstractSheet *insertSheet(int index,
|
||||
const QString &name = QString(),
|
||||
AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet);
|
||||
bool renameSheet(int index, const QString &name);
|
||||
bool deleteSheet(int index);
|
||||
bool copySheet(int index, const QString &newName = QString());
|
||||
bool moveSheet(int srcIndex, int distIndex);
|
||||
|
||||
AbstractSheet *activeSheet() const;
|
||||
bool setActiveSheet(int index);
|
||||
|
||||
// void addChart();
|
||||
bool defineName(const QString &name,
|
||||
const QString &formula,
|
||||
const QString &comment = QString(),
|
||||
const QString &scope = QString());
|
||||
bool isDate1904() const;
|
||||
void setDate1904(bool date1904);
|
||||
bool isStringsToNumbersEnabled() const;
|
||||
void setStringsToNumbersEnabled(bool enable = true);
|
||||
bool isStringsToHyperlinksEnabled() const;
|
||||
void setStringsToHyperlinksEnabled(bool enable = true);
|
||||
bool isHtmlToRichStringEnabled() const;
|
||||
void setHtmlToRichStringEnabled(bool enable = true);
|
||||
QString defaultDateFormat() const;
|
||||
void setDefaultDateFormat(const QString &format);
|
||||
|
||||
// internal used member
|
||||
void addMediaFile(std::shared_ptr<MediaFile> media, bool force = false);
|
||||
QList<std::shared_ptr<MediaFile>> mediaFiles() const;
|
||||
void addChartFile(std::shared_ptr<Chart> chartFile);
|
||||
QList<std::shared_ptr<Chart>> chartFiles() const;
|
||||
|
||||
private:
|
||||
friend class Worksheet;
|
||||
friend class Chartsheet;
|
||||
friend class WorksheetPrivate;
|
||||
friend class Document;
|
||||
friend class DocumentPrivate;
|
||||
|
||||
Workbook(Workbook::CreateFlag flag);
|
||||
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
|
||||
SharedStrings *sharedStrings() const;
|
||||
Styles *styles();
|
||||
Theme *theme();
|
||||
QList<QImage> images();
|
||||
QList<Drawing *> drawings();
|
||||
QList<std::shared_ptr<AbstractSheet>> getSheetsByTypes(AbstractSheet::SheetType type) const;
|
||||
QStringList worksheetNames() const;
|
||||
AbstractSheet *addSheet(const QString &name,
|
||||
int sheetId,
|
||||
AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXWORKBOOK_H
|
|
@ -0,0 +1,77 @@
|
|||
// xlsxworkbook_p.h
|
||||
|
||||
#ifndef XLSXWORKBOOK_P_H
|
||||
#define XLSXWORKBOOK_P_H
|
||||
|
||||
#include "xlsxabstractooxmlfile_p.h"
|
||||
#include "xlsxrelationships_p.h"
|
||||
#include "xlsxsimpleooxmlfile_p.h"
|
||||
#include "xlsxtheme_p.h"
|
||||
#include "xlsxworkbook.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
struct XlsxDefineNameData {
|
||||
XlsxDefineNameData()
|
||||
: sheetId(-1)
|
||||
{
|
||||
}
|
||||
XlsxDefineNameData(const QString &name,
|
||||
const QString &formula,
|
||||
const QString &comment,
|
||||
int sheetId = -1)
|
||||
: name(name)
|
||||
, formula(formula)
|
||||
, comment(comment)
|
||||
, sheetId(sheetId)
|
||||
{
|
||||
}
|
||||
QString name;
|
||||
QString formula;
|
||||
QString comment;
|
||||
// using internal sheetId, instead of the localSheetId(order in the workbook)
|
||||
int sheetId;
|
||||
};
|
||||
|
||||
class WorkbookPrivate : public AbstractOOXmlFilePrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(Workbook)
|
||||
public:
|
||||
WorkbookPrivate(Workbook *q, Workbook::CreateFlag flag);
|
||||
|
||||
std::shared_ptr<SharedStrings> sharedStrings;
|
||||
QList<std::shared_ptr<AbstractSheet>> sheets;
|
||||
QList<std::shared_ptr<SimpleOOXmlFile>> externalLinks;
|
||||
QStringList sheetNames;
|
||||
std::shared_ptr<Styles> styles;
|
||||
std::shared_ptr<Theme> theme;
|
||||
QList<std::shared_ptr<MediaFile>> mediaFiles;
|
||||
QList<std::shared_ptr<Chart>> chartFiles;
|
||||
QList<XlsxDefineNameData> definedNamesList;
|
||||
|
||||
bool strings_to_numbers_enabled;
|
||||
bool strings_to_hyperlinks_enabled;
|
||||
bool html_to_richstring_enabled;
|
||||
bool date1904;
|
||||
QString defaultDateFormat;
|
||||
|
||||
int x_window;
|
||||
int y_window;
|
||||
int window_width;
|
||||
int window_height;
|
||||
|
||||
int activesheetIndex;
|
||||
int firstsheet;
|
||||
int table_count;
|
||||
|
||||
// Used to generate new sheet name and id
|
||||
int last_worksheet_index;
|
||||
int last_chartsheet_index;
|
||||
int last_sheet_id;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // XLSXWORKBOOK_P_H
|
|
@ -0,0 +1,197 @@
|
|||
// xlsxworksheet.h
|
||||
|
||||
#ifndef XLSXWORKSHEET_H
|
||||
#define XLSXWORKSHEET_H
|
||||
|
||||
#include "xlsxabstractsheet.h"
|
||||
#include "xlsxcell.h"
|
||||
#include "xlsxcelllocation.h"
|
||||
#include "xlsxcellrange.h"
|
||||
#include "xlsxcellreference.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QIODevice>
|
||||
#include <QImage>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QPointF>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
#include <QVariant>
|
||||
|
||||
class WorksheetTest;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class DocumentPrivate;
|
||||
class Workbook;
|
||||
class Format;
|
||||
class Drawing;
|
||||
class DataValidation;
|
||||
class ConditionalFormatting;
|
||||
class CellRange;
|
||||
class RichString;
|
||||
class Relationships;
|
||||
class Chart;
|
||||
|
||||
class WorksheetPrivate;
|
||||
class QXLSX_EXPORT Worksheet : public AbstractSheet
|
||||
{
|
||||
Q_DECLARE_PRIVATE(Worksheet)
|
||||
|
||||
private:
|
||||
friend class DocumentPrivate;
|
||||
friend class Workbook;
|
||||
friend class ::WorksheetTest;
|
||||
Worksheet(const QString &sheetName, int sheetId, Workbook *book, CreateFlag flag);
|
||||
Worksheet *copy(const QString &distName, int distId) const override;
|
||||
|
||||
public:
|
||||
~Worksheet();
|
||||
|
||||
public:
|
||||
bool write(const CellReference &row_column,
|
||||
const QVariant &value,
|
||||
const Format &format = Format());
|
||||
bool write(int row, int column, const QVariant &value, const Format &format = Format());
|
||||
|
||||
QVariant read(const CellReference &row_column) const;
|
||||
QVariant read(int row, int column) const;
|
||||
|
||||
bool writeString(const CellReference &row_column,
|
||||
const QString &value,
|
||||
const Format &format = Format());
|
||||
bool writeString(int row, int column, const QString &value, const Format &format = Format());
|
||||
bool writeString(const CellReference &row_column,
|
||||
const RichString &value,
|
||||
const Format &format = Format());
|
||||
bool writeString(int row, int column, const RichString &value, const Format &format = Format());
|
||||
|
||||
bool writeInlineString(const CellReference &row_column,
|
||||
const QString &value,
|
||||
const Format &format = Format());
|
||||
bool writeInlineString(int row,
|
||||
int column,
|
||||
const QString &value,
|
||||
const Format &format = Format());
|
||||
|
||||
bool writeNumeric(const CellReference &row_column,
|
||||
double value,
|
||||
const Format &format = Format());
|
||||
bool writeNumeric(int row, int column, double value, const Format &format = Format());
|
||||
|
||||
bool writeFormula(const CellReference &row_column,
|
||||
const CellFormula &formula,
|
||||
const Format &format = Format(),
|
||||
double result = 0);
|
||||
bool writeFormula(int row,
|
||||
int column,
|
||||
const CellFormula &formula,
|
||||
const Format &format = Format(),
|
||||
double result = 0);
|
||||
|
||||
bool writeBlank(const CellReference &row_column, const Format &format = Format());
|
||||
bool writeBlank(int row, int column, const Format &format = Format());
|
||||
|
||||
bool writeBool(const CellReference &row_column, bool value, const Format &format = Format());
|
||||
bool writeBool(int row, int column, bool value, const Format &format = Format());
|
||||
|
||||
bool writeDateTime(const CellReference &row_column,
|
||||
const QDateTime &dt,
|
||||
const Format &format = Format());
|
||||
bool writeDateTime(int row, int column, const QDateTime &dt, const Format &format = Format());
|
||||
|
||||
// dev67
|
||||
bool writeDate(const CellReference &row_column,
|
||||
const QDate &dt,
|
||||
const Format &format = Format());
|
||||
bool writeDate(int row, int column, const QDate &dt, const Format &format = Format());
|
||||
|
||||
bool
|
||||
writeTime(const CellReference &row_column, const QTime &t, const Format &format = Format());
|
||||
bool writeTime(int row, int column, const QTime &t, const Format &format = Format());
|
||||
|
||||
bool writeHyperlink(const CellReference &row_column,
|
||||
const QUrl &url,
|
||||
const Format &format = Format(),
|
||||
const QString &display = QString(),
|
||||
const QString &tip = QString());
|
||||
bool writeHyperlink(int row,
|
||||
int column,
|
||||
const QUrl &url,
|
||||
const Format &format = Format(),
|
||||
const QString &display = QString(),
|
||||
const QString &tip = QString());
|
||||
|
||||
bool addDataValidation(const DataValidation &validation);
|
||||
bool addConditionalFormatting(const ConditionalFormatting &cf);
|
||||
|
||||
std::shared_ptr<Cell> cellAt(const CellReference &row_column) const;
|
||||
std::shared_ptr<Cell> cellAt(int row, int column) const;
|
||||
|
||||
int insertImage(int row, int column, const QImage &image);
|
||||
bool getImage(int imageIndex, QImage &img);
|
||||
bool getImage(int row, int column, QImage &img);
|
||||
uint getImageCount();
|
||||
|
||||
Chart *insertChart(int row, int column, const QSize &size);
|
||||
|
||||
bool mergeCells(const CellRange &range, const Format &format = Format());
|
||||
bool unmergeCells(const CellRange &range);
|
||||
QList<CellRange> mergedCells() const;
|
||||
|
||||
bool setColumnWidth(const CellRange &range, double width);
|
||||
bool setColumnFormat(const CellRange &range, const Format &format);
|
||||
bool setColumnHidden(const CellRange &range, bool hidden);
|
||||
bool setColumnWidth(int colFirst, int colLast, double width);
|
||||
bool setColumnFormat(int colFirst, int colLast, const Format &format);
|
||||
bool setColumnHidden(int colFirst, int colLast, bool hidden);
|
||||
|
||||
double columnWidth(int column);
|
||||
Format columnFormat(int column);
|
||||
bool isColumnHidden(int column);
|
||||
|
||||
bool setRowHeight(int rowFirst, int rowLast, double height);
|
||||
bool setRowFormat(int rowFirst, int rowLast, const Format &format);
|
||||
bool setRowHidden(int rowFirst, int rowLast, bool hidden);
|
||||
|
||||
double rowHeight(int row);
|
||||
Format rowFormat(int row);
|
||||
bool isRowHidden(int row);
|
||||
|
||||
bool groupRows(int rowFirst, int rowLast, bool collapsed = true);
|
||||
bool groupColumns(int colFirst, int colLast, bool collapsed = true);
|
||||
bool groupColumns(const CellRange &range, bool collapsed = true);
|
||||
CellRange dimension() const;
|
||||
|
||||
bool isWindowProtected() const;
|
||||
void setWindowProtected(bool protect);
|
||||
bool isFormulasVisible() const;
|
||||
void setFormulasVisible(bool visible);
|
||||
bool isGridLinesVisible() const;
|
||||
void setGridLinesVisible(bool visible);
|
||||
bool isRowColumnHeadersVisible() const;
|
||||
void setRowColumnHeadersVisible(bool visible);
|
||||
bool isZerosVisible() const;
|
||||
void setZerosVisible(bool visible);
|
||||
bool isRightToLeft() const;
|
||||
void setRightToLeft(bool enable);
|
||||
bool isSelected() const;
|
||||
void setSelected(bool select);
|
||||
bool isRulerVisible() const;
|
||||
void setRulerVisible(bool visible);
|
||||
bool isOutlineSymbolsVisible() const;
|
||||
void setOutlineSymbolsVisible(bool visible);
|
||||
bool isWhiteSpaceVisible() const;
|
||||
void setWhiteSpaceVisible(bool visible);
|
||||
bool setStartPage(int spagen); // add by liufeijin20181028
|
||||
|
||||
QVector<CellLocation> getFullCells(int *maxRow, int *maxCol) const;
|
||||
|
||||
private:
|
||||
void saveToXmlFile(QIODevice *device) const override;
|
||||
bool loadFromXmlFile(QIODevice *device) override;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif // XLSXWORKSHEET_H
|
|
@ -0,0 +1,294 @@
|
|||
// xlsxworksheet_p.h
|
||||
|
||||
#ifndef XLSXWORKSHEET_P_H
|
||||
#define XLSXWORKSHEET_P_H
|
||||
|
||||
#include "xlsxabstractsheet_p.h"
|
||||
#include "xlsxcell.h"
|
||||
#include "xlsxcellformula.h"
|
||||
#include "xlsxconditionalformatting.h"
|
||||
#include "xlsxdatavalidation.h"
|
||||
#include "xlsxworksheet.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QImage>
|
||||
#include <QObject>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
class QXmlStreamWriter;
|
||||
class QXmlStreamReader;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class SharedStrings;
|
||||
|
||||
struct XlsxHyperlinkData {
|
||||
enum LinkType { External, Internal };
|
||||
|
||||
XlsxHyperlinkData(LinkType linkType = External,
|
||||
const QString &target = QString(),
|
||||
const QString &location = QString(),
|
||||
const QString &display = QString(),
|
||||
const QString &tip = QString())
|
||||
: linkType(linkType)
|
||||
, target(target)
|
||||
, location(location)
|
||||
, display(display)
|
||||
, tooltip(tip)
|
||||
{
|
||||
}
|
||||
|
||||
LinkType linkType;
|
||||
QString target; // For External link
|
||||
QString location;
|
||||
QString display;
|
||||
QString tooltip;
|
||||
};
|
||||
|
||||
// ECMA-376 Part1 18.3.1.81
|
||||
struct XlsxSheetFormatProps {
|
||||
XlsxSheetFormatProps(
|
||||
int baseColWidth = 8,
|
||||
bool customHeight = false,
|
||||
double defaultColWidth =
|
||||
8.430f, // https://learn.microsoft.com/en-us/office/troubleshoot/excel/determine-column-widths
|
||||
double defaultRowHeight = 15,
|
||||
quint8 outlineLevelCol = 0,
|
||||
quint8 outlineLevelRow = 0,
|
||||
bool thickBottom = false,
|
||||
bool thickTop = false,
|
||||
bool zeroHeight = false)
|
||||
: baseColWidth(baseColWidth)
|
||||
, customHeight(customHeight)
|
||||
, defaultColWidth(defaultColWidth)
|
||||
, defaultRowHeight(defaultRowHeight)
|
||||
, outlineLevelCol(outlineLevelCol)
|
||||
, outlineLevelRow(outlineLevelRow)
|
||||
, thickBottom(thickBottom)
|
||||
, thickTop(thickTop)
|
||||
, zeroHeight(zeroHeight)
|
||||
{
|
||||
}
|
||||
|
||||
int baseColWidth;
|
||||
bool customHeight;
|
||||
double defaultColWidth;
|
||||
double defaultRowHeight;
|
||||
quint8 outlineLevelCol;
|
||||
quint8 outlineLevelRow;
|
||||
bool thickBottom;
|
||||
bool thickTop;
|
||||
bool zeroHeight;
|
||||
};
|
||||
|
||||
struct XlsxRowInfo {
|
||||
XlsxRowInfo(double height = 0, const Format &format = Format(), bool hidden = false)
|
||||
: customHeight(false)
|
||||
, height(height)
|
||||
, format(format)
|
||||
, hidden(hidden)
|
||||
, outlineLevel(0)
|
||||
, collapsed(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool customHeight;
|
||||
double height;
|
||||
Format format;
|
||||
bool hidden;
|
||||
int outlineLevel;
|
||||
bool collapsed;
|
||||
};
|
||||
|
||||
struct XlsxColumnInfo {
|
||||
XlsxColumnInfo(int firstColumn, // = 0,
|
||||
int lastColumn, // = 1,
|
||||
bool isSetWidth,
|
||||
double width = 0,
|
||||
const Format &format = Format(),
|
||||
bool hidden = false)
|
||||
: width(width)
|
||||
, format(format)
|
||||
, firstColumn(firstColumn)
|
||||
, lastColumn(lastColumn)
|
||||
, outlineLevel(0)
|
||||
, isSetWidth(isSetWidth)
|
||||
, customWidth(false)
|
||||
, hidden(hidden)
|
||||
, collapsed(false)
|
||||
{
|
||||
}
|
||||
|
||||
double width;
|
||||
Format format;
|
||||
int firstColumn;
|
||||
int lastColumn;
|
||||
int outlineLevel;
|
||||
bool isSetWidth;
|
||||
bool customWidth;
|
||||
bool hidden;
|
||||
bool collapsed;
|
||||
};
|
||||
|
||||
class CellTable
|
||||
{
|
||||
public:
|
||||
static QList<int> sorteIntList(QList<int> &&keys)
|
||||
{
|
||||
std::sort(keys.begin(), keys.end());
|
||||
return keys;
|
||||
}
|
||||
|
||||
inline QList<int> sortedRows() const
|
||||
{
|
||||
QList<int> keys = cells.keys();
|
||||
std::sort(keys.begin(), keys.end());
|
||||
return keys;
|
||||
}
|
||||
|
||||
void setValue(int row, int column, const std::shared_ptr<Cell> &cell)
|
||||
{
|
||||
cells[row].insert(column, cell);
|
||||
firstRow = qMin(firstRow, row);
|
||||
firstColumn = qMin(firstColumn, column);
|
||||
lastRow = qMin(lastRow, row);
|
||||
lastColumn = qMin(lastColumn, column);
|
||||
}
|
||||
|
||||
std::shared_ptr<Cell> cellAt(int row, int column) const
|
||||
{
|
||||
return cells.value(row).value(column);
|
||||
}
|
||||
|
||||
bool contains(int row, int column) const
|
||||
{
|
||||
auto it = cells.find(row);
|
||||
if (it != cells.end()) {
|
||||
return it->contains(column);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isEmpty() const { return cells.isEmpty(); }
|
||||
|
||||
// It's faster with a single QHash, but in Qt5 it's capacity limits
|
||||
// how much cells we can hold
|
||||
QHash<int, QHash<int, std::shared_ptr<Cell>>> cells;
|
||||
int firstRow = -1;
|
||||
int firstColumn = -1;
|
||||
int lastRow = -1;
|
||||
int lastColumn = -1;
|
||||
};
|
||||
|
||||
class WorksheetPrivate : public AbstractSheetPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(Worksheet)
|
||||
|
||||
public:
|
||||
WorksheetPrivate(Worksheet *p, Worksheet::CreateFlag flag);
|
||||
~WorksheetPrivate();
|
||||
|
||||
public:
|
||||
int checkDimensions(int row, int col, bool ignore_row = false, bool ignore_col = false);
|
||||
Format cellFormat(int row, int col) const;
|
||||
QString generateDimensionString() const;
|
||||
void calculateSpans() const;
|
||||
void splitColsInfo(int colFirst, int colLast);
|
||||
void validateDimension();
|
||||
|
||||
void saveXmlSheetData(QXmlStreamWriter &writer) const;
|
||||
void saveXmlCellData(QXmlStreamWriter &writer,
|
||||
int row,
|
||||
int col,
|
||||
std::shared_ptr<Cell> cell) const;
|
||||
void saveXmlMergeCells(QXmlStreamWriter &writer) const;
|
||||
void saveXmlHyperlinks(QXmlStreamWriter &writer) const;
|
||||
void saveXmlDrawings(QXmlStreamWriter &writer) const;
|
||||
void saveXmlDataValidations(QXmlStreamWriter &writer) const;
|
||||
|
||||
int rowPixelsSize(int row) const;
|
||||
int colPixelsSize(int col) const;
|
||||
|
||||
void loadXmlSheetData(QXmlStreamReader &reader);
|
||||
void loadXmlColumnsInfo(QXmlStreamReader &reader);
|
||||
void loadXmlMergeCells(QXmlStreamReader &reader);
|
||||
void loadXmlDataValidations(QXmlStreamReader &reader);
|
||||
void loadXmlSheetFormatProps(QXmlStreamReader &reader);
|
||||
void loadXmlSheetViews(QXmlStreamReader &reader);
|
||||
void loadXmlHyperlinks(QXmlStreamReader &reader);
|
||||
|
||||
QList<std::shared_ptr<XlsxRowInfo>> getRowInfoList(int rowFirst, int rowLast);
|
||||
QList<std::shared_ptr<XlsxColumnInfo>> getColumnInfoList(int colFirst, int colLast);
|
||||
QList<int> getColumnIndexes(int colFirst, int colLast);
|
||||
bool isColumnRangeValid(int colFirst, int colLast);
|
||||
|
||||
SharedStrings *sharedStrings() const;
|
||||
|
||||
public:
|
||||
CellTable cellTable;
|
||||
|
||||
QHash<int, QHash<int, QString>> comments;
|
||||
QHash<int, QHash<int, std::shared_ptr<XlsxHyperlinkData>>> urlTable;
|
||||
QList<CellRange> merges;
|
||||
QHash<int, std::shared_ptr<XlsxRowInfo>> rowsInfo;
|
||||
QHash<int, std::shared_ptr<XlsxColumnInfo>> colsInfo;
|
||||
QHash<int, std::shared_ptr<XlsxColumnInfo>> colsInfoHelper;
|
||||
|
||||
QList<DataValidation> dataValidationsList;
|
||||
QList<ConditionalFormatting> conditionalFormattingList;
|
||||
|
||||
QHash<int, CellFormula> sharedFormulaMap; // shared formula map
|
||||
|
||||
CellRange dimension;
|
||||
|
||||
mutable QHash<int, QString> row_spans;
|
||||
QHash<int, double> row_sizes;
|
||||
QHash<int, double> col_sizes;
|
||||
|
||||
// pagesetup and print settings add by liufeijin 20181028, liufeijin
|
||||
QString PpaperSize;
|
||||
QString Pscale;
|
||||
QString PfirstPageNumber;
|
||||
QString Porientation;
|
||||
QString PuseFirstPageNumber;
|
||||
QString PhorizontalDpi;
|
||||
QString PverticalDpi;
|
||||
QString Prid;
|
||||
QString Pcopies;
|
||||
|
||||
// pageMargins, liufeijin
|
||||
QString PMheader;
|
||||
QString PMfooter;
|
||||
QString PMtop;
|
||||
QString PMbotton;
|
||||
QString PMleft;
|
||||
QString PMright;
|
||||
|
||||
// header footer, liufeijin
|
||||
QString MoodFooter;
|
||||
QString ModdHeader;
|
||||
QString MoodalignWithMargins; // add align 20190619
|
||||
|
||||
XlsxSheetFormatProps sheetFormatProps;
|
||||
|
||||
bool windowProtection;
|
||||
bool showFormulas;
|
||||
bool showGridLines;
|
||||
bool showRowColHeaders;
|
||||
bool showZeros;
|
||||
bool rightToLeft;
|
||||
bool tabSelected;
|
||||
bool showRuler;
|
||||
bool showOutlineSymbols;
|
||||
bool showWhiteSpace;
|
||||
|
||||
QRegularExpression urlPattern;
|
||||
|
||||
private:
|
||||
static double calculateColWidth(int characters);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
#endif // XLSXWORKSHEET_P_H
|
|
@ -0,0 +1,36 @@
|
|||
// xlsxzipreader_p.h
|
||||
|
||||
#ifndef QXLSX_XLSXZIPREADER_P_H
|
||||
#define QXLSX_XLSXZIPREADER_P_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QScopedPointer>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
class QZipReader;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class ZipReader
|
||||
{
|
||||
public:
|
||||
explicit ZipReader(const QString &fileName);
|
||||
explicit ZipReader(QIODevice *device);
|
||||
~ZipReader();
|
||||
bool exists() const;
|
||||
QStringList filePaths() const;
|
||||
QByteArray fileData(const QString &fileName) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ZipReader)
|
||||
void init();
|
||||
QScopedPointer<QZipReader> m_reader;
|
||||
QStringList m_filePaths;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_XLSXZIPREADER_P_H
|
|
@ -0,0 +1,33 @@
|
|||
// xlsxzipwriter_p.h
|
||||
|
||||
#ifndef QXLSX_ZIPWRITER_H
|
||||
#define QXLSX_ZIPWRITER_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QString>
|
||||
|
||||
class QZipWriter;
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
class ZipWriter
|
||||
{
|
||||
public:
|
||||
explicit ZipWriter(const QString &filePath);
|
||||
explicit ZipWriter(QIODevice *device);
|
||||
~ZipWriter();
|
||||
|
||||
void addFile(const QString &filePath, QIODevice *device);
|
||||
void addFile(const QString &filePath, const QByteArray &data);
|
||||
bool error() const;
|
||||
void close();
|
||||
|
||||
private:
|
||||
QZipWriter *m_writer;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
#endif // QXLSX_ZIPWRITER_H
|
|
@ -0,0 +1,95 @@
|
|||
// xlsxabstractooxmlfile.cpp
|
||||
|
||||
#include "xlsxabstractooxmlfile.h"
|
||||
|
||||
#include "xlsxabstractooxmlfile_p.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QByteArray>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
AbstractOOXmlFilePrivate::AbstractOOXmlFilePrivate(
|
||||
AbstractOOXmlFile *q,
|
||||
AbstractOOXmlFile::CreateFlag flag = AbstractOOXmlFile::F_NewFromScratch)
|
||||
: relationships(new Relationships)
|
||||
, flag(flag)
|
||||
, q_ptr(q)
|
||||
{
|
||||
}
|
||||
|
||||
AbstractOOXmlFilePrivate::~AbstractOOXmlFilePrivate()
|
||||
{
|
||||
delete relationships;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*
|
||||
* \class AbstractOOXmlFile
|
||||
*
|
||||
* Base class of all the ooxml part file.
|
||||
*/
|
||||
|
||||
AbstractOOXmlFile::AbstractOOXmlFile(CreateFlag flag)
|
||||
: d_ptr(new AbstractOOXmlFilePrivate(this, flag))
|
||||
{
|
||||
}
|
||||
|
||||
AbstractOOXmlFile::AbstractOOXmlFile(AbstractOOXmlFilePrivate *d)
|
||||
: d_ptr(d)
|
||||
{
|
||||
}
|
||||
|
||||
AbstractOOXmlFile::~AbstractOOXmlFile()
|
||||
{
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
QByteArray AbstractOOXmlFile::saveToXmlData() const
|
||||
{
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
saveToXmlFile(&buffer);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
bool AbstractOOXmlFile::loadFromXmlData(const QByteArray &data)
|
||||
{
|
||||
QBuffer buffer;
|
||||
buffer.setData(data);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
return loadFromXmlFile(&buffer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
void AbstractOOXmlFile::setFilePath(const QString path)
|
||||
{
|
||||
Q_D(AbstractOOXmlFile);
|
||||
d->filePathInPackage = path;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
QString AbstractOOXmlFile::filePath() const
|
||||
{
|
||||
Q_D(const AbstractOOXmlFile);
|
||||
return d->filePathInPackage;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
Relationships *AbstractOOXmlFile::relationships() const
|
||||
{
|
||||
Q_D(const AbstractOOXmlFile);
|
||||
return d->relationships;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,187 @@
|
|||
// xlsxabstractsheet.cpp
|
||||
|
||||
#include "xlsxabstractsheet.h"
|
||||
|
||||
#include "xlsxabstractsheet_p.h"
|
||||
#include "xlsxworkbook.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
AbstractSheetPrivate::AbstractSheetPrivate(AbstractSheet *p, AbstractSheet::CreateFlag flag)
|
||||
: AbstractOOXmlFilePrivate(p, flag)
|
||||
{
|
||||
type = AbstractSheet::ST_WorkSheet;
|
||||
sheetState = AbstractSheet::SS_Visible;
|
||||
}
|
||||
|
||||
AbstractSheetPrivate::~AbstractSheetPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\class AbstractSheet
|
||||
\inmodule QtXlsx
|
||||
\brief Base class for worksheet, chartsheet, etc.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum AbstractSheet::SheetType
|
||||
|
||||
\value ST_WorkSheet
|
||||
\value ST_ChartSheet
|
||||
\omitvalue ST_DialogSheet
|
||||
\omitvalue ST_MacroSheet
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum AbstractSheet::SheetState
|
||||
|
||||
\value SS_Visible
|
||||
\value SS_Hidden
|
||||
\value SS_VeryHidden User can't make a veryHidden sheet visible in normal way.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn AbstractSheet::copy(const QString &distName, int distId) const
|
||||
|
||||
Copies the current sheet to a sheet called \a distName with \a distId.
|
||||
Returns the new sheet.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
AbstractSheet::AbstractSheet(const QString &name,
|
||||
int id,
|
||||
Workbook *workbook,
|
||||
AbstractSheetPrivate *d)
|
||||
: AbstractOOXmlFile(d)
|
||||
{
|
||||
d_func()->name = name;
|
||||
d_func()->id = id;
|
||||
d_func()->workbook = workbook;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the name of the sheet.
|
||||
*/
|
||||
QString AbstractSheet::sheetName() const
|
||||
{
|
||||
Q_D(const AbstractSheet);
|
||||
return d->name;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
void AbstractSheet::setSheetName(const QString &sheetName)
|
||||
{
|
||||
Q_D(AbstractSheet);
|
||||
d->name = sheetName;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the type of the sheet.
|
||||
*/
|
||||
AbstractSheet::SheetType AbstractSheet::sheetType() const
|
||||
{
|
||||
Q_D(const AbstractSheet);
|
||||
return d->type;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
void AbstractSheet::setSheetType(SheetType type)
|
||||
{
|
||||
Q_D(AbstractSheet);
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the state of the sheet.
|
||||
*
|
||||
* \sa isHidden(), isVisible(), setSheetState()
|
||||
*/
|
||||
AbstractSheet::SheetState AbstractSheet::sheetState() const
|
||||
{
|
||||
Q_D(const AbstractSheet);
|
||||
return d->sheetState;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Set the state of the sheet to \a state.
|
||||
*/
|
||||
void AbstractSheet::setSheetState(SheetState state)
|
||||
{
|
||||
Q_D(AbstractSheet);
|
||||
d->sheetState = state;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns true if the sheet is not visible, otherwise false will be returned.
|
||||
*
|
||||
* \sa sheetState(), setHidden()
|
||||
*/
|
||||
bool AbstractSheet::isHidden() const
|
||||
{
|
||||
Q_D(const AbstractSheet);
|
||||
return d->sheetState != SS_Visible;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns true if the sheet is visible.
|
||||
*/
|
||||
bool AbstractSheet::isVisible() const
|
||||
{
|
||||
return !isHidden();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Make the sheet hidden or visible based on \a hidden.
|
||||
*/
|
||||
void AbstractSheet::setHidden(bool hidden)
|
||||
{
|
||||
Q_D(AbstractSheet);
|
||||
if (hidden == isHidden())
|
||||
return;
|
||||
|
||||
d->sheetState = hidden ? SS_Hidden : SS_Visible;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Convenience function, equivalent to setHidden(! \a visible).
|
||||
*/
|
||||
void AbstractSheet::setVisible(bool visible)
|
||||
{
|
||||
setHidden(!visible);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
int AbstractSheet::sheetId() const
|
||||
{
|
||||
Q_D(const AbstractSheet);
|
||||
return d->id;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
Drawing *AbstractSheet::drawing() const
|
||||
{
|
||||
Q_D(const AbstractSheet);
|
||||
return d->drawing.get();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return the workbook
|
||||
*/
|
||||
Workbook *AbstractSheet::workbook() const
|
||||
{
|
||||
Q_D(const AbstractSheet);
|
||||
return d->workbook;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,332 @@
|
|||
// xlsxcell.cpp
|
||||
|
||||
#include "xlsxcell.h"
|
||||
|
||||
#include "xlsxcell_p.h"
|
||||
#include "xlsxformat.h"
|
||||
#include "xlsxformat_p.h"
|
||||
#include "xlsxutility_p.h"
|
||||
#include "xlsxworkbook.h"
|
||||
#include "xlsxworksheet.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QTime>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
CellPrivate::CellPrivate(Cell *p)
|
||||
: q_ptr(p)
|
||||
{
|
||||
}
|
||||
|
||||
CellPrivate::CellPrivate(const CellPrivate *const cp)
|
||||
: parent(cp->parent)
|
||||
, cellType(cp->cellType)
|
||||
, value(cp->value)
|
||||
, formula(cp->formula)
|
||||
, format(cp->format)
|
||||
, richString(cp->richString)
|
||||
, styleNumber(cp->styleNumber)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\class Cell
|
||||
\inmodule QtXlsx
|
||||
\brief The Cell class provides a API that is used to handle the worksheet cell.
|
||||
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum Cell::CellType
|
||||
\value BooleanType Boolean type
|
||||
\value NumberType Number type, can be blank or used with formula
|
||||
\value ErrorType Error type
|
||||
\value SharedStringType Shared string type
|
||||
\value StringType String type, can be used with formula
|
||||
\value InlineStringType Inline string type
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* Created by Worksheet only.
|
||||
*/
|
||||
// qint32 styleIndex = (-1)
|
||||
Cell::Cell(const QVariant &data,
|
||||
CellType type,
|
||||
const Format &format,
|
||||
Worksheet *parent,
|
||||
qint32 styleIndex)
|
||||
: d_ptr(new CellPrivate(this))
|
||||
{
|
||||
d_ptr->value = data;
|
||||
d_ptr->cellType = type;
|
||||
d_ptr->format = format;
|
||||
d_ptr->parent = parent;
|
||||
d_ptr->styleNumber = styleIndex;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
Cell::Cell(const Cell *const cell)
|
||||
: d_ptr(new CellPrivate(cell->d_ptr))
|
||||
{
|
||||
d_ptr->q_ptr = this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Destroys the Cell and cleans up.
|
||||
*/
|
||||
Cell::~Cell()
|
||||
{
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return the dataType of this Cell
|
||||
*/
|
||||
Cell::CellType Cell::cellType() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
return d->cellType;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return the data content of this Cell
|
||||
*/
|
||||
QVariant Cell::value() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
return d->value;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return the data content of this Cell for reading
|
||||
*/
|
||||
QVariant Cell::readValue() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
QVariant ret; // return value
|
||||
ret = d->value;
|
||||
|
||||
Format fmt = this->format();
|
||||
|
||||
if (isDateTime()) {
|
||||
QVariant vDT = dateTime();
|
||||
if (vDT.isNull()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// https://github.com/QtExcel/QXlsx/issues/171
|
||||
// https://www.qt.io/blog/whats-new-in-qmetatype-qvariant
|
||||
#if QT_VERSION >= 0x060000 // Qt 6.0 or over
|
||||
if (vDT.metaType().id() == QMetaType::QDateTime) {
|
||||
ret = vDT;
|
||||
} else if (vDT.metaType().id() == QMetaType::QDate) {
|
||||
ret = vDT;
|
||||
} else if (vDT.metaType().id() == QMetaType::QTime) {
|
||||
ret = vDT;
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
#else
|
||||
if (vDT.type() == QVariant::DateTime) {
|
||||
ret = vDT;
|
||||
} else if (vDT.type() == QVariant::Date) {
|
||||
ret = vDT;
|
||||
} else if (vDT.type() == QVariant::Time) {
|
||||
ret = vDT;
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
#endif
|
||||
|
||||
// QDateTime dt = dateTime();
|
||||
// ret = dt;
|
||||
|
||||
// QString strFormat = fmt.numberFormat();
|
||||
// if (!strFormat.isEmpty())
|
||||
// {
|
||||
// // TODO: use number format
|
||||
// }
|
||||
|
||||
// qint32 styleNo = d->styleNumber;
|
||||
|
||||
// if (styleNo == 10)
|
||||
// {
|
||||
// }
|
||||
|
||||
// if (styleNo == 11)
|
||||
// {
|
||||
// QTime timeValue = dt.time(); // only time. (HH:mm:ss)
|
||||
// ret = timeValue;
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
// if (styleNo == 12)
|
||||
// {
|
||||
// }
|
||||
|
||||
// if (styleNo == 13) // (HH:mm:ss)
|
||||
// {
|
||||
// double dValue = d->value.toDouble();
|
||||
// int day = int(dValue); // unit is day.
|
||||
// double deciamlPointValue1 = dValue - double(day);
|
||||
|
||||
// double dHour = deciamlPointValue1 * (double(1.0) / double(24.0));
|
||||
// int hour = int(dHour);
|
||||
|
||||
// double deciamlPointValue2 = deciamlPointValue1 - (double(hour) * (double(1.0) /
|
||||
// double(24.0))); double dMin = deciamlPointValue2 * (double(1.0) / double(60.0)); int min
|
||||
// = int(dMin);
|
||||
|
||||
// double deciamlPointValue3 = deciamlPointValue2 - (double(min) * (double(1.0) /
|
||||
// double(60.0))); double dSec = deciamlPointValue3 * (double(1.0) / double(60.0)); int sec
|
||||
// = int(dSec);
|
||||
|
||||
// int totalHour = hour + (day * 24);
|
||||
|
||||
// QString strTime;
|
||||
// strTime = QString("%1:%2:%3").arg(totalHour).arg(min).arg(sec);
|
||||
// ret = strTime;
|
||||
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
// return ret;
|
||||
// */
|
||||
}
|
||||
|
||||
if (hasFormula()) {
|
||||
QString formulaString = this->formula().formulaText();
|
||||
ret = formulaString;
|
||||
return ret; // return formula string
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return the style used by this Cell. If no style used, 0 will be returned.
|
||||
*/
|
||||
Format Cell::format() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
return d->format;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns true if the cell has one formula.
|
||||
*/
|
||||
bool Cell::hasFormula() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
return d->formula.isValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return the formula contents if the dataType is Formula
|
||||
*/
|
||||
CellFormula Cell::formula() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
return d->formula;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns whether the value is probably a dateTime or not
|
||||
*/
|
||||
bool Cell::isDateTime() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
Cell::CellType cellType = d->cellType;
|
||||
double dValue = d->value.toDouble(); // number
|
||||
// QString strValue = d->value.toString().toUtf8();
|
||||
bool isValidFormat = d->format.isValid();
|
||||
bool isDateTimeFormat = d->format.isDateTimeFormat(); // datetime format
|
||||
|
||||
// dev67
|
||||
if (cellType == NumberType || cellType == DateType || cellType == CustomType) {
|
||||
if (dValue >= 0 && isValidFormat && isDateTimeFormat) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return the data time value.
|
||||
*/
|
||||
/*
|
||||
QDateTime Cell::dateTime() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
if (!isDateTime())
|
||||
return QDateTime();
|
||||
|
||||
return datetimeFromNumber(d->value.toDouble(), d->parent->workbook()->isDate1904());
|
||||
}
|
||||
*/
|
||||
QVariant Cell::dateTime() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
if (!isDateTime()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// dev57
|
||||
|
||||
QVariant ret;
|
||||
double dValue = d->value.toDouble();
|
||||
bool isDate1904 = d->parent->workbook()->isDate1904();
|
||||
ret = datetimeFromNumber(dValue, isDate1904);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns whether the cell is probably a rich string or not
|
||||
*/
|
||||
bool Cell::isRichString() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
if (d->cellType != SharedStringType && d->cellType != InlineStringType &&
|
||||
d->cellType != StringType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return d->richString.isRichString();
|
||||
}
|
||||
|
||||
qint32 Cell::styleNumber() const
|
||||
{
|
||||
Q_D(const Cell);
|
||||
|
||||
qint32 ret = d->styleNumber;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Cell::isDateType(CellType cellType, const Format &format)
|
||||
{
|
||||
if (cellType == NumberType || cellType == DateType || cellType == CustomType) {
|
||||
return format.isValid() && format.isDateTimeFormat();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,440 @@
|
|||
// xlsxcellformula.cpp
|
||||
|
||||
#include "xlsxcellformula.h"
|
||||
|
||||
#include "xlsxcellformula_p.h"
|
||||
#include "xlsxutility_p.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
CellFormulaPrivate::CellFormulaPrivate(const QString &formula_,
|
||||
const CellRange &ref_,
|
||||
CellFormula::FormulaType type_)
|
||||
: formula(formula_)
|
||||
, type(type_)
|
||||
, reference(ref_)
|
||||
, ca(false)
|
||||
, si(0)
|
||||
{
|
||||
// Remove the formula '=' sign if exists
|
||||
if (formula.startsWith(QLatin1String("=")))
|
||||
formula.remove(0, 1);
|
||||
else if (formula.startsWith(QLatin1String("{=")) && formula.endsWith(QLatin1String("}")))
|
||||
formula = formula.mid(2, formula.length() - 3);
|
||||
}
|
||||
|
||||
CellFormulaPrivate::CellFormulaPrivate(const CellFormulaPrivate &other)
|
||||
: QSharedData(other)
|
||||
, formula(other.formula)
|
||||
, type(other.type)
|
||||
, reference(other.reference)
|
||||
, ca(other.ca)
|
||||
, si(other.si)
|
||||
{
|
||||
}
|
||||
|
||||
CellFormulaPrivate::~CellFormulaPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\class CellFormula
|
||||
\inmodule QtXlsx
|
||||
\brief The CellFormula class provides a API that is used to handle the cell formula.
|
||||
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum CellFormula::FormulaType
|
||||
\value NormalType
|
||||
\value ArrayType
|
||||
\value DataTableType
|
||||
\value SharedType
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Creates a new formula.
|
||||
*/
|
||||
CellFormula::CellFormula()
|
||||
{
|
||||
// The d pointer is initialized with a null pointer
|
||||
}
|
||||
|
||||
/*!
|
||||
* Creates a new formula with the given \a formula and \a type.
|
||||
*/
|
||||
CellFormula::CellFormula(const char *formula, FormulaType type)
|
||||
: d(new CellFormulaPrivate(QString::fromLatin1(formula), CellRange(), type))
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* Creates a new formula with the given \a formula and \a type.
|
||||
*/
|
||||
CellFormula::CellFormula(const QString &formula, FormulaType type)
|
||||
: d(new CellFormulaPrivate(formula, CellRange(), type))
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* Creates a new formula with the given \a formula, \a ref and \a type.
|
||||
*/
|
||||
CellFormula::CellFormula(const QString &formula, const CellRange &ref, FormulaType type)
|
||||
: d(new CellFormulaPrivate(formula, ref, type))
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new formula with the same attributes as the \a other formula.
|
||||
*/
|
||||
CellFormula::CellFormula(const CellFormula &other)
|
||||
: d(other.d)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Assigns the \a other formula to this formula, and returns a
|
||||
reference to this formula.
|
||||
*/
|
||||
CellFormula &CellFormula::operator=(const CellFormula &other)
|
||||
{
|
||||
if (this != &other) // Self-assignment check [cert-oop54-cpp]
|
||||
{
|
||||
this->d = other.d;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Destroys this formula.
|
||||
*/
|
||||
CellFormula::~CellFormula()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the type of the formula.
|
||||
*/
|
||||
CellFormula::FormulaType CellFormula::formulaType() const
|
||||
{
|
||||
return d ? d->type : NormalType;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the contents of the formula.
|
||||
*/
|
||||
QString CellFormula::formulaText() const
|
||||
{
|
||||
return d ? d->formula : QString();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the reference cells of the formula. For normal formula,
|
||||
* this will return an invalid CellRange object.
|
||||
*/
|
||||
CellRange CellFormula::reference() const
|
||||
{
|
||||
return d ? d->reference : CellRange();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns whether the formula is valid.
|
||||
*/
|
||||
bool CellFormula::isValid() const
|
||||
{
|
||||
return d;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the shared index for shared formula.
|
||||
*/
|
||||
int CellFormula::sharedIndex() const
|
||||
{
|
||||
return d && d->type == SharedType ? d->si : (-1);
|
||||
}
|
||||
|
||||
/* aca (Always Calculate Array) // not-implemented attribute
|
||||
*
|
||||
* Only applies to array formulas.
|
||||
*
|
||||
* true indicates that the entire array shall be calculated in full.
|
||||
* If false the individual cells of the array shall be calculated as needed.
|
||||
*
|
||||
* The aca value shall be ignored unless the value of the corresponding
|
||||
* t attribute is array.
|
||||
*
|
||||
* [Note: The primary case where an array formula must be calculated in
|
||||
* part instead of in full is when some cells in the array depend on other
|
||||
* cells that are semi-calculated, e.g., contains the function =(). end note]
|
||||
*
|
||||
* The possible values for this attribute are defined by the W3C XML Schema
|
||||
* boolean datatype.
|
||||
*/
|
||||
|
||||
/* bx (Assigns Value to Name) // not-implemented attribute
|
||||
*
|
||||
* Specifies that this formula assigns a value to a name.
|
||||
*
|
||||
* The possible values for this attribute are defined by the W3C XML
|
||||
* Schema boolean datatype.
|
||||
*/
|
||||
|
||||
/* del1 (Input 1 Deleted) // not-implemented attribute
|
||||
*
|
||||
* Whether the first input cell for data table has been deleted.
|
||||
* Applies to data table formula only. Written on master cell of data table
|
||||
* formula only.
|
||||
*
|
||||
* The possible values for this attribute are defined by the W3C XML Schema
|
||||
* boolean datatype.
|
||||
*/
|
||||
|
||||
/* del2 (Input 2 Deleted) // not-implemented attribute
|
||||
*
|
||||
* Whether the second input cell for data table has been deleted.
|
||||
* Applies to data table formula only. Written on master cell of data
|
||||
* table formula only.
|
||||
*
|
||||
* The possible values for this attribute are defined by the W3C XML Schema
|
||||
* boolean datatype.
|
||||
*/
|
||||
|
||||
/* dt2D (Data Table 2-D) // not-implemented attribute
|
||||
*
|
||||
* Data table is two-dimensional. Only applies to the data tables function.
|
||||
* Written on master cell of data table formula only.
|
||||
*
|
||||
* The possible values for this attribute are defined by the W3C XML Schema
|
||||
* boolean datatype.
|
||||
*/
|
||||
|
||||
/* dtr (Data Table Row) // not-implemented attribute
|
||||
*
|
||||
* true if one-dimensional data table is a row, otherwise it's a column.
|
||||
* Only applies to the data tables function. Written on master cell of data
|
||||
* table formula only.
|
||||
*
|
||||
* The possible values for this attribute are defined by the W3C XML Schema
|
||||
* boolean datatype.
|
||||
*/
|
||||
|
||||
/* r1 (Data Table Cell 1) // not-implemented attribute
|
||||
*
|
||||
* First input cell for data table. Only applies to the data tables array
|
||||
* function "TABLE()". Written on master cell of data table formula only.
|
||||
*
|
||||
* The possible values for this attribute are defined by the ST_CellRef
|
||||
* simple type (§18.18.7).
|
||||
*/
|
||||
|
||||
/* r2 (Input Cell 2) // not-implemented attribute
|
||||
*
|
||||
* Second input cell for data table when dt2D is '1'. Only applies to the
|
||||
* data tables array function "TABLE()".Written on master cell of data table
|
||||
* formula only.
|
||||
*
|
||||
* The possible values for this attribute are defined by the ST_CellRef
|
||||
* simple type (§18.18.7).
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \remark pair with loadFromXml()
|
||||
*/
|
||||
bool CellFormula::saveToXml(QXmlStreamWriter &writer) const
|
||||
{
|
||||
|
||||
// t (Formula Type)
|
||||
//
|
||||
// Type of formula.
|
||||
// The possible values for this attribute are defined by the
|
||||
// ST_CellFormulaType simple type (§18.18.6).
|
||||
//
|
||||
// 18.18.6 ST_CellFormulaType (Formula Type)
|
||||
// array (Array Formula)
|
||||
// dataTable (Table Formula)
|
||||
// normal (Normal)
|
||||
// shared (Shared Formula)
|
||||
|
||||
QString t;
|
||||
switch (d->type) {
|
||||
case CellFormula::ArrayType:
|
||||
t = QStringLiteral("array");
|
||||
break;
|
||||
case CellFormula::SharedType:
|
||||
t = QStringLiteral("shared");
|
||||
break;
|
||||
case CellFormula::NormalType:
|
||||
t = QStringLiteral("normal");
|
||||
break;
|
||||
case CellFormula::DataTableType:
|
||||
t = QStringLiteral("dataTable");
|
||||
break;
|
||||
default: // undefined type
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// f (Formula)
|
||||
//
|
||||
// Formula for the cell. The formula expression is contained in the
|
||||
// character node of this element.
|
||||
writer.writeStartElement(QStringLiteral("f"));
|
||||
|
||||
if (!t.isEmpty()) {
|
||||
writer.writeAttribute(QStringLiteral("t"), t); // write type(t)
|
||||
}
|
||||
|
||||
// ref (Range of Cells)
|
||||
//
|
||||
// Range of cells which the formula applies to.
|
||||
// Only required for shared formula, array formula or data table.
|
||||
// Only written on the master formula,
|
||||
// not subsequent formulas belonging to the same shared group, array,
|
||||
// or data table.
|
||||
// The possible values for this attribute are defined by the ST_Ref
|
||||
// simple type (§18.18.62).
|
||||
|
||||
if (d->type == CellFormula::SharedType || d->type == CellFormula::ArrayType ||
|
||||
d->type == CellFormula::DataTableType) {
|
||||
if (d->reference.isValid()) {
|
||||
writer.writeAttribute(QStringLiteral("ref"), d->reference.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// ca (Calculate Cell)
|
||||
//
|
||||
// Indicates that this formula needs to be recalculated the next time
|
||||
// calculation is performed. [Example: This is always set on volatile
|
||||
// functions, like =(), and circular references. end example]
|
||||
// The possible values for this attribute are defined by the W3C XML
|
||||
// Schema boolean datatype.
|
||||
//
|
||||
// 3.2.2 boolean
|
||||
// 3.2.2.1 Lexical representation
|
||||
// An instance of a datatype that is defined as ·boolean· can have the
|
||||
// following legal literals {true, false, 1, 0}.
|
||||
|
||||
if (d->ca) {
|
||||
writer.writeAttribute(QStringLiteral("ca"), QStringLiteral("1"));
|
||||
}
|
||||
|
||||
// si (Shared Group Index)
|
||||
// Optional attribute to optimize load performance by sharing formulas.
|
||||
//
|
||||
// When a formula is a shared formula (t value is shared) then this value
|
||||
// indicates the group to which this particular cell's formula belongs. The
|
||||
// first formula in a group of shared formulas is saved in the f element.
|
||||
// This is considered the 'master' formula cell. Subsequent cells sharing
|
||||
// this formula need not have the formula written in their f element.
|
||||
// Instead, the attribute si value for a particular cell is used to figure
|
||||
// what the formula expression should be based on the cell's relative
|
||||
// location to the master formula cell.
|
||||
|
||||
if (d->type == CellFormula::SharedType) {
|
||||
int si = d->si;
|
||||
writer.writeAttribute(QStringLiteral("si"), QString::number(si));
|
||||
}
|
||||
|
||||
if (!d->formula.isEmpty()) {
|
||||
QString strFormula = d->formula;
|
||||
writer.writeCharacters(strFormula); // write formula
|
||||
}
|
||||
|
||||
writer.writeEndElement(); // f
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \remark pair with saveToXml()
|
||||
*/
|
||||
bool CellFormula::loadFromXml(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("f"));
|
||||
if (!d)
|
||||
d = new CellFormulaPrivate(QString(), CellRange(), NormalType);
|
||||
|
||||
QXmlStreamAttributes attributes = reader.attributes();
|
||||
QString typeString = attributes.value(QLatin1String("t")).toString();
|
||||
|
||||
// branch: shared-formula
|
||||
//
|
||||
if (typeString == QLatin1String("array")) {
|
||||
d->type = ArrayType;
|
||||
} else if (typeString == QLatin1String("shared")) {
|
||||
d->type = SharedType;
|
||||
} else if (typeString == QLatin1String("normal")) {
|
||||
d->type = NormalType;
|
||||
} else if (typeString == QLatin1String("dataTable")) {
|
||||
d->type = DataTableType;
|
||||
} else {
|
||||
/*
|
||||
// undefined type
|
||||
// qDebug() << "Undefined type" << typeString;
|
||||
return false;
|
||||
// */
|
||||
|
||||
// dev40 {{
|
||||
// https://github.com/QtExcel/QXlsx/issues/38
|
||||
d->type = NormalType; // Change: normal Type is not mentioned in the xml file!!!!!
|
||||
// }}
|
||||
}
|
||||
|
||||
// branch: shared-formula
|
||||
//
|
||||
// ref (Range of Cells)
|
||||
// Range of cells which the formula applies to.
|
||||
// Only required for shared formula, array formula or data table.
|
||||
if (d->type == CellFormula::SharedType || d->type == CellFormula::ArrayType ||
|
||||
d->type == CellFormula::DataTableType) {
|
||||
if (attributes.hasAttribute(QLatin1String("ref"))) {
|
||||
QString refString = attributes.value(QLatin1String("ref")).toString();
|
||||
d->reference = CellRange(refString);
|
||||
}
|
||||
}
|
||||
|
||||
// branch: shared-formula
|
||||
//
|
||||
// si (Shared Group Index)
|
||||
// Optional attribute to optimize load performance by sharing formulas.
|
||||
// When a formula is a shared formula (t value is shared) then this value
|
||||
// indicates the group to which this particular cell's formula belongs.
|
||||
if (d->type == CellFormula::SharedType) {
|
||||
QString ca = attributes.value(QLatin1String("si")).toString();
|
||||
d->ca = parseXsdBoolean(ca, false);
|
||||
|
||||
if (attributes.hasAttribute(QLatin1String("si"))) {
|
||||
d->si = attributes.value(QLatin1String("si")).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
d->formula = reader.readElementText(); // read formula
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
bool CellFormula::operator==(const CellFormula &formula) const
|
||||
{
|
||||
return d->formula == formula.d->formula && d->type == formula.d->type && d->si == formula.d->si;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
bool CellFormula::operator!=(const CellFormula &formula) const
|
||||
{
|
||||
return d->formula != formula.d->formula || d->type != formula.d->type || d->si != formula.d->si;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,23 @@
|
|||
// xlsxcelllocation.cpp
|
||||
|
||||
#include "xlsxcelllocation.h"
|
||||
|
||||
#include "xlsxcell.h"
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
CellLocation::CellLocation()
|
||||
{
|
||||
col = -1;
|
||||
row = -1;
|
||||
|
||||
cell.reset();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,138 @@
|
|||
// xlsxcellrange.cpp
|
||||
|
||||
#include "xlsxcellrange.h"
|
||||
|
||||
#include "xlsxcellreference.h"
|
||||
|
||||
#include <QPoint>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
/*!
|
||||
\class CellRange
|
||||
\brief For a range "A1:B2" or single cell "A1"
|
||||
\inmodule QtXlsx
|
||||
|
||||
The CellRange class stores the top left and bottom
|
||||
right rows and columns of a range in a worksheet.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs an range, i.e. a range
|
||||
whose rowCount() and columnCount() are 0.
|
||||
*/
|
||||
CellRange::CellRange()
|
||||
: top(-1)
|
||||
, left(-1)
|
||||
, bottom(-2)
|
||||
, right(-2)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs the range from the given \a top, \a
|
||||
left, \a bottom and \a right rows and columns.
|
||||
|
||||
\sa topRow(), leftColumn(), bottomRow(), rightColumn()
|
||||
*/
|
||||
CellRange::CellRange(int top, int left, int bottom, int right)
|
||||
: top(top)
|
||||
, left(left)
|
||||
, bottom(bottom)
|
||||
, right(right)
|
||||
{
|
||||
}
|
||||
|
||||
CellRange::CellRange(const CellReference &topLeft, const CellReference &bottomRight)
|
||||
: top(topLeft.row())
|
||||
, left(topLeft.column())
|
||||
, bottom(bottomRight.row())
|
||||
, right(bottomRight.column())
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Constructs the range form the given \a range string.
|
||||
*/
|
||||
CellRange::CellRange(const QString &range)
|
||||
{
|
||||
init(range);
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Constructs the range form the given \a range string.
|
||||
*/
|
||||
CellRange::CellRange(const char *range)
|
||||
{
|
||||
init(QString::fromLatin1(range));
|
||||
}
|
||||
|
||||
void CellRange::init(const QString &range)
|
||||
{
|
||||
QStringList rs = range.split(QLatin1Char(':'));
|
||||
if (rs.size() == 2) {
|
||||
CellReference start(rs[0]);
|
||||
CellReference end(rs[1]);
|
||||
top = start.row();
|
||||
left = start.column();
|
||||
bottom = end.row();
|
||||
right = end.column();
|
||||
} else {
|
||||
CellReference p(rs[0]);
|
||||
top = p.row();
|
||||
left = p.column();
|
||||
bottom = p.row();
|
||||
right = p.column();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a the range by copying the given \a
|
||||
other range.
|
||||
*/
|
||||
CellRange::CellRange(const CellRange &other)
|
||||
: top(other.top)
|
||||
, left(other.left)
|
||||
, bottom(other.bottom)
|
||||
, right(other.right)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the range.
|
||||
*/
|
||||
CellRange::~CellRange()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Convert the range to string notation, such as "A1:B5".
|
||||
*/
|
||||
QString CellRange::toString(bool row_abs, bool col_abs) const
|
||||
{
|
||||
if (!isValid())
|
||||
return QString();
|
||||
|
||||
if (left == right && top == bottom) {
|
||||
// Single cell
|
||||
return CellReference(top, left).toString(row_abs, col_abs);
|
||||
}
|
||||
|
||||
QString cell_1 = CellReference(top, left).toString(row_abs, col_abs);
|
||||
QString cell_2 = CellReference(bottom, right).toString(row_abs, col_abs);
|
||||
return cell_1 + QLatin1String(":") + cell_2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns true if the Range is valid.
|
||||
*/
|
||||
bool CellRange::isValid() const
|
||||
{
|
||||
return left <= right && top <= bottom;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,142 @@
|
|||
// xlsxcellreference.cpp
|
||||
|
||||
#include "xlsxcellreference.h"
|
||||
#include "xlsxworksheet_p.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QRegularExpression>
|
||||
#include <QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
namespace {
|
||||
|
||||
int intPow(int x, int p)
|
||||
{
|
||||
if (p == 0)
|
||||
return 1;
|
||||
if (p == 1)
|
||||
return x;
|
||||
|
||||
int tmp = intPow(x, p / 2);
|
||||
if (p % 2 == 0)
|
||||
return tmp * tmp;
|
||||
else
|
||||
return x * tmp * tmp;
|
||||
}
|
||||
|
||||
QString col_to_name(int col_num)
|
||||
{
|
||||
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;
|
||||
}
|
||||
return col_str;
|
||||
}
|
||||
|
||||
int col_from_name(const QString &col_str)
|
||||
{
|
||||
int col = 0;
|
||||
int expn = 0;
|
||||
for (int i = col_str.size() - 1; i > -1; --i) {
|
||||
col += (col_str[i].unicode() - 'A' + 1) * intPow(26, expn);
|
||||
expn++;
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/*!
|
||||
\class CellReference
|
||||
\brief For one single cell such as "A1"
|
||||
\inmodule QtXlsx
|
||||
|
||||
The CellReference class stores the cell location in a worksheet.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs an invalid Cell Reference
|
||||
*/
|
||||
CellReference::CellReference() = default;
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Constructs the Reference form the given \a cell string.
|
||||
*/
|
||||
CellReference::CellReference(const QString &cell)
|
||||
{
|
||||
init(cell);
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Constructs the Reference form the given \a cell string.
|
||||
*/
|
||||
CellReference::CellReference(const char *cell)
|
||||
{
|
||||
init(QString::fromLatin1(cell));
|
||||
}
|
||||
|
||||
void CellReference::init(const QString &cell_str)
|
||||
{
|
||||
static const 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a Reference by copying the given \a
|
||||
other Reference.
|
||||
*/
|
||||
CellReference::CellReference(const CellReference &other)
|
||||
: _row(other._row)
|
||||
, _column(other._column)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the Reference.
|
||||
*/
|
||||
CellReference::~CellReference()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Convert the Reference to string notation, such as "A1" or "$A$1".
|
||||
If current object is invalid, an empty string will be returned.
|
||||
*/
|
||||
QString CellReference::toString(bool row_abs, bool col_abs) const
|
||||
{
|
||||
if (!isValid())
|
||||
return {};
|
||||
|
||||
QString cell_str;
|
||||
if (col_abs)
|
||||
cell_str.append(QLatin1Char('$'));
|
||||
cell_str.append(col_to_name(_column));
|
||||
if (row_abs)
|
||||
cell_str.append(QLatin1Char('$'));
|
||||
cell_str.append(QString::number(_row));
|
||||
return cell_str;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns true if the Reference is valid.
|
||||
*/
|
||||
bool CellReference::isValid() const
|
||||
{
|
||||
return _row > 0 && _column > 0;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,146 @@
|
|||
// xlsxchartsheet.cpp
|
||||
|
||||
#include "xlsxchartsheet.h"
|
||||
|
||||
#include "xlsxchart.h"
|
||||
#include "xlsxchartsheet_p.h"
|
||||
#include "xlsxdrawing_p.h"
|
||||
#include "xlsxdrawinganchor_p.h"
|
||||
#include "xlsxutility_p.h"
|
||||
#include "xlsxworkbook.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
ChartsheetPrivate::ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag)
|
||||
: AbstractSheetPrivate(p, flag)
|
||||
, chart(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ChartsheetPrivate::~ChartsheetPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\class Chartsheet
|
||||
\inmodule QtXlsx
|
||||
\brief Represent one chartsheet in the workbook.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
Chartsheet::Chartsheet(const QString &name, int id, Workbook *workbook, CreateFlag flag)
|
||||
: AbstractSheet(name, id, workbook, new ChartsheetPrivate(this, flag))
|
||||
{
|
||||
setSheetType(ST_ChartSheet);
|
||||
|
||||
if (flag == Chartsheet::F_NewFromScratch) {
|
||||
d_func()->drawing = std::make_shared<Drawing>(this, flag);
|
||||
|
||||
auto anchor = new DrawingAbsoluteAnchor(drawing(), DrawingAnchor::Picture);
|
||||
|
||||
anchor->pos = QPoint(0, 0);
|
||||
anchor->ext = QSize(9293679, 6068786);
|
||||
|
||||
auto chart = std::shared_ptr<Chart>(new Chart(this, flag));
|
||||
chart->setChartType(Chart::CT_BarChart);
|
||||
anchor->setObjectGraphicFrame(chart);
|
||||
|
||||
d_func()->chart = chart.get();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*
|
||||
* Make a copy of this sheet.
|
||||
*/
|
||||
|
||||
Chartsheet *Chartsheet::copy(const QString &distName, int distId) const
|
||||
{
|
||||
//: Todo
|
||||
Q_UNUSED(distName)
|
||||
Q_UNUSED(distId)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Destroys this workssheet.
|
||||
*/
|
||||
Chartsheet::~Chartsheet()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the chart object of the sheet.
|
||||
*/
|
||||
Chart *Chartsheet::chart()
|
||||
{
|
||||
Q_D(Chartsheet);
|
||||
|
||||
return d->chart;
|
||||
}
|
||||
|
||||
void Chartsheet::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
Q_D(const Chartsheet);
|
||||
d->relationships->clear();
|
||||
|
||||
QXmlStreamWriter writer(device);
|
||||
|
||||
writer.writeStartDocument(QStringLiteral("1.0"), true);
|
||||
writer.writeDefaultNamespace(
|
||||
QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main"));
|
||||
writer.writeNamespace(
|
||||
QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"),
|
||||
QStringLiteral("r"));
|
||||
writer.writeStartElement(QStringLiteral("chartsheet"));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("sheetViews"));
|
||||
writer.writeEmptyElement(QStringLiteral("sheetView"));
|
||||
writer.writeAttribute(QStringLiteral("workbookViewId"), QString::number(0));
|
||||
writer.writeAttribute(QStringLiteral("zoomToFit"), QStringLiteral("1"));
|
||||
writer.writeEndElement(); // sheetViews
|
||||
|
||||
int idx = d->workbook->drawings().indexOf(d->drawing.get());
|
||||
d->relationships->addWorksheetRelationship(
|
||||
QStringLiteral("/drawing"), QStringLiteral("../drawings/drawing%1.xml").arg(idx + 1));
|
||||
|
||||
writer.writeEmptyElement(QStringLiteral("drawing"));
|
||||
writer.writeAttribute(QStringLiteral("r:id"),
|
||||
QStringLiteral("rId%1").arg(d->relationships->count()));
|
||||
|
||||
writer.writeEndElement(); // chartsheet
|
||||
writer.writeEndDocument();
|
||||
}
|
||||
|
||||
bool Chartsheet::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
Q_D(Chartsheet);
|
||||
|
||||
QXmlStreamReader reader(device);
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("drawing")) {
|
||||
QString rId = reader.attributes().value(QStringLiteral("r:id")).toString();
|
||||
QString name = d->relationships->getRelationshipById(rId).target;
|
||||
|
||||
const auto parts = splitPath(filePath());
|
||||
QString path = QDir::cleanPath(parts.first() + QLatin1String("/") + name);
|
||||
|
||||
d->drawing = std::make_shared<Drawing>(this, F_LoadFromExists);
|
||||
d->drawing->setFilePath(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,200 @@
|
|||
// xlsxcolor.cpp
|
||||
|
||||
#include "xlsxcolor_p.h"
|
||||
#include "xlsxstyles_p.h"
|
||||
#include "xlsxutility_p.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
XlsxColor::XlsxColor(const QColor &color)
|
||||
{
|
||||
if (color.isValid())
|
||||
val.setValue(color);
|
||||
}
|
||||
|
||||
XlsxColor::XlsxColor(const QString &theme, const QString &tint)
|
||||
: val(QStringList() << theme << tint)
|
||||
{
|
||||
}
|
||||
|
||||
XlsxColor::XlsxColor(int index)
|
||||
: val(index)
|
||||
{
|
||||
}
|
||||
|
||||
bool XlsxColor::isRgbColor() const
|
||||
{
|
||||
return val.userType() == qMetaTypeId<QColor>() && val.value<QColor>().isValid();
|
||||
}
|
||||
|
||||
bool XlsxColor::isIndexedColor() const
|
||||
{
|
||||
return val.userType() == QMetaType::Int;
|
||||
}
|
||||
|
||||
bool XlsxColor::isThemeColor() const
|
||||
{
|
||||
return val.userType() == QMetaType::QStringList;
|
||||
}
|
||||
|
||||
bool XlsxColor::isInvalid() const
|
||||
{
|
||||
return !val.isValid();
|
||||
}
|
||||
|
||||
QColor XlsxColor::rgbColor() const
|
||||
{
|
||||
return isRgbColor() ? val.value<QColor>() : QColor();
|
||||
}
|
||||
|
||||
int XlsxColor::indexedColor() const
|
||||
{
|
||||
return isIndexedColor() ? val.toInt() : -1;
|
||||
}
|
||||
|
||||
QStringList XlsxColor::themeColor() const
|
||||
{
|
||||
return isThemeColor() ? val.toStringList() : QStringList();
|
||||
}
|
||||
|
||||
bool XlsxColor::saveToXml(QXmlStreamWriter &writer, const QString &node) const
|
||||
{
|
||||
if (!node.isEmpty())
|
||||
writer.writeEmptyElement(node); // color, bgColor, fgColor
|
||||
else
|
||||
writer.writeEmptyElement(QStringLiteral("color"));
|
||||
|
||||
if (val.userType() == qMetaTypeId<QColor>()) {
|
||||
writer.writeAttribute(QStringLiteral("rgb"), XlsxColor::toARGBString(val.value<QColor>()));
|
||||
} else if (val.userType() == QMetaType::QStringList) {
|
||||
QStringList themes = val.toStringList();
|
||||
writer.writeAttribute(QStringLiteral("theme"), themes[0]);
|
||||
if (!themes[1].isEmpty())
|
||||
writer.writeAttribute(QStringLiteral("tint"), themes[1]);
|
||||
} else if (val.userType() == QMetaType::Int) {
|
||||
writer.writeAttribute(QStringLiteral("indexed"), val.toString());
|
||||
} else {
|
||||
writer.writeAttribute(QStringLiteral("auto"), QStringLiteral("1"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XlsxColor::loadFromXml(QXmlStreamReader &reader)
|
||||
{
|
||||
const auto &attributes = reader.attributes();
|
||||
|
||||
if (attributes.hasAttribute(QLatin1String("rgb"))) {
|
||||
const auto &colorString = attributes.value(QLatin1String("rgb")).toString();
|
||||
val.setValue(fromARGBString(colorString));
|
||||
} else if (attributes.hasAttribute(QLatin1String("indexed"))) {
|
||||
int index = attributes.value(QLatin1String("indexed")).toInt();
|
||||
val.setValue(index);
|
||||
} else if (attributes.hasAttribute(QLatin1String("theme"))) {
|
||||
const auto &theme = attributes.value(QLatin1String("theme")).toString();
|
||||
const auto &tint = attributes.value(QLatin1String("tint")).toString();
|
||||
val.setValue(QStringList() << theme << tint);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
XlsxColor::operator QVariant() const
|
||||
{
|
||||
const auto &cref
|
||||
#if QT_VERSION >= 0x060000 // Qt 6.0 or over
|
||||
= QMetaType::fromType<XlsxColor>();
|
||||
#else
|
||||
= qMetaTypeId<XlsxColor>();
|
||||
#endif
|
||||
return QVariant(cref, this);
|
||||
}
|
||||
|
||||
QColor XlsxColor::fromARGBString(const QString &c)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
|
||||
if (c.startsWith(u'#')) {
|
||||
return QColor::fromString(c);
|
||||
} else {
|
||||
return QColor::fromString(QLatin1Char('#') + c);
|
||||
}
|
||||
#else
|
||||
QColor color;
|
||||
if (c.startsWith(u'#')) {
|
||||
color.setNamedColor(c);
|
||||
} else {
|
||||
color.setNamedColor(QLatin1Char('#') + c);
|
||||
}
|
||||
return color;
|
||||
#endif
|
||||
}
|
||||
|
||||
QString XlsxColor::toARGBString(const QColor &c)
|
||||
{
|
||||
return QString::asprintf("%02X%02X%02X%02X", c.alpha(), c.red(), c.green(), c.blue());
|
||||
}
|
||||
|
||||
#if !defined(QT_NO_DATASTREAM)
|
||||
QDataStream &operator<<(QDataStream &s, const XlsxColor &color)
|
||||
{
|
||||
if (color.isInvalid())
|
||||
s << 0;
|
||||
else if (color.isRgbColor())
|
||||
s << 1 << color.rgbColor();
|
||||
else if (color.isIndexedColor())
|
||||
s << 2 << color.indexedColor();
|
||||
else if (color.isThemeColor())
|
||||
s << 3 << color.themeColor();
|
||||
else
|
||||
s << 4;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &s, XlsxColor &color)
|
||||
{
|
||||
int marker(4);
|
||||
s >> marker;
|
||||
if (marker == 0) {
|
||||
color = XlsxColor();
|
||||
} else if (marker == 1) {
|
||||
QColor c;
|
||||
s >> c;
|
||||
color = XlsxColor(c);
|
||||
} else if (marker == 2) {
|
||||
int indexed;
|
||||
s >> indexed;
|
||||
color = XlsxColor(indexed);
|
||||
} else if (marker == 3) {
|
||||
QStringList list;
|
||||
s >> list;
|
||||
color = XlsxColor(list[0], list[1]);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
QDebug operator<<(QDebug dbg, const XlsxColor &c)
|
||||
{
|
||||
if (c.isInvalid())
|
||||
dbg.nospace() << "XlsxColor(invalid)";
|
||||
else if (c.isRgbColor())
|
||||
dbg.nospace() << c.rgbColor();
|
||||
else if (c.isIndexedColor())
|
||||
dbg.nospace() << "XlsxColor(indexed," << c.indexedColor() << ")";
|
||||
else if (c.isThemeColor())
|
||||
dbg.nospace() << "XlsxColor(theme," << c.themeColor().join(QLatin1Char(':')) << ')';
|
||||
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,814 @@
|
|||
// xlsxconditionalformatting.cpp
|
||||
|
||||
#include "xlsxconditionalformatting.h"
|
||||
|
||||
#include "xlsxcellrange.h"
|
||||
#include "xlsxconditionalformatting_p.h"
|
||||
#include "xlsxstyles_p.h"
|
||||
#include "xlsxworksheet.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
ConditionalFormattingPrivate::ConditionalFormattingPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
ConditionalFormattingPrivate::ConditionalFormattingPrivate(
|
||||
const ConditionalFormattingPrivate &other)
|
||||
: QSharedData(other)
|
||||
{
|
||||
}
|
||||
|
||||
ConditionalFormattingPrivate::~ConditionalFormattingPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
void ConditionalFormattingPrivate::writeCfVo(QXmlStreamWriter &writer,
|
||||
const XlsxCfVoData &cfvo) const
|
||||
{
|
||||
writer.writeEmptyElement(QStringLiteral("cfvo"));
|
||||
QString type;
|
||||
switch (cfvo.type) {
|
||||
case ConditionalFormatting::VOT_Formula:
|
||||
type = QStringLiteral("formula");
|
||||
break;
|
||||
case ConditionalFormatting::VOT_Max:
|
||||
type = QStringLiteral("max");
|
||||
break;
|
||||
case ConditionalFormatting::VOT_Min:
|
||||
type = QStringLiteral("min");
|
||||
break;
|
||||
case ConditionalFormatting::VOT_Num:
|
||||
type = QStringLiteral("num");
|
||||
break;
|
||||
case ConditionalFormatting::VOT_Percent:
|
||||
type = QStringLiteral("percent");
|
||||
break;
|
||||
case ConditionalFormatting::VOT_Percentile:
|
||||
type = QStringLiteral("percentile");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
writer.writeAttribute(QStringLiteral("type"), type);
|
||||
writer.writeAttribute(QStringLiteral("val"), cfvo.value);
|
||||
if (!cfvo.gte)
|
||||
writer.writeAttribute(QStringLiteral("gte"), QStringLiteral("0"));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \class ConditionalFormatting
|
||||
* \brief Conditional formatting for single cell or ranges
|
||||
* \inmodule QtXlsx
|
||||
*
|
||||
* The conditional formatting can be applied to a single cell or ranges of cells.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum ConditionalFormatting::HighlightRuleType
|
||||
|
||||
\value Highlight_LessThan
|
||||
\value Highlight_LessThanOrEqual
|
||||
\value Highlight_Equal
|
||||
\value Highlight_NotEqual
|
||||
\value Highlight_GreaterThanOrEqual
|
||||
\value Highlight_GreaterThan
|
||||
\value Highlight_Between
|
||||
\value Highlight_NotBetween
|
||||
|
||||
\value Highlight_ContainsText
|
||||
\value Highlight_NotContainsText
|
||||
\value Highlight_BeginsWith
|
||||
\value Highlight_EndsWith
|
||||
|
||||
\value Highlight_TimePeriod
|
||||
|
||||
\value Highlight_Duplicate
|
||||
\value Highlight_Unique
|
||||
|
||||
\value Highlight_Blanks
|
||||
\value Highlight_NoBlanks
|
||||
\value Highlight_Errors
|
||||
\value Highlight_NoErrors
|
||||
|
||||
\value Highlight_Top
|
||||
\value Highlight_TopPercent
|
||||
\value Highlight_Bottom
|
||||
\value Highlight_BottomPercent
|
||||
|
||||
\value Highlight_AboveAverage
|
||||
\value Highlight_AboveOrEqualAverage
|
||||
\value Highlight_BelowAverage
|
||||
\value Highlight_BelowOrEqualAverage
|
||||
\value Highlight_AboveStdDev1
|
||||
\value Highlight_AboveStdDev2
|
||||
\value Highlight_AboveStdDev3
|
||||
\value Highlight_BelowStdDev1
|
||||
\value Highlight_BelowStdDev2
|
||||
\value Highlight_BelowStdDev3
|
||||
|
||||
\value Highlight_Expression
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum ConditionalFormatting::ValueObjectType
|
||||
|
||||
\value VOT_Formula
|
||||
\value VOT_Max
|
||||
\value VOT_Min
|
||||
\value VOT_Num
|
||||
\value VOT_Percent
|
||||
\value VOT_Percentile
|
||||
*/
|
||||
|
||||
/*!
|
||||
Construct a conditional formatting object
|
||||
*/
|
||||
ConditionalFormatting::ConditionalFormatting()
|
||||
: d(new ConditionalFormattingPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a copy of \a other.
|
||||
*/
|
||||
ConditionalFormatting::ConditionalFormatting(const ConditionalFormatting &other)
|
||||
: d(other.d)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Assigns \a other to this conditional formatting and returns a reference to
|
||||
this conditional formatting.
|
||||
*/
|
||||
ConditionalFormatting &ConditionalFormatting::operator=(const ConditionalFormatting &other)
|
||||
{
|
||||
if (this != &other) // Self-assignment check [cert-oop54-cpp]
|
||||
{
|
||||
this->d = other.d;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Destroy the object.
|
||||
*/
|
||||
ConditionalFormatting::~ConditionalFormatting()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add a highlight rule with the given \a type, \a formula1, \a formula2,
|
||||
* \a format and \a stopIfTrue.
|
||||
* Return false if failed.
|
||||
*/
|
||||
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type,
|
||||
const QString &formula1,
|
||||
const QString &formula2,
|
||||
const Format &format,
|
||||
bool stopIfTrue)
|
||||
{
|
||||
if (format.isEmpty())
|
||||
return false;
|
||||
|
||||
bool skipFormula = false;
|
||||
|
||||
auto cfRule = std::make_shared<XlsxCfRuleData>();
|
||||
if (type >= Highlight_LessThan && type <= Highlight_NotBetween) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("cellIs");
|
||||
QString op;
|
||||
switch (type) {
|
||||
case Highlight_Between:
|
||||
op = QStringLiteral("between");
|
||||
break;
|
||||
case Highlight_Equal:
|
||||
op = QStringLiteral("equal");
|
||||
break;
|
||||
case Highlight_GreaterThan:
|
||||
op = QStringLiteral("greaterThan");
|
||||
break;
|
||||
case Highlight_GreaterThanOrEqual:
|
||||
op = QStringLiteral("greaterThanOrEqual");
|
||||
break;
|
||||
case Highlight_LessThan:
|
||||
op = QStringLiteral("lessThan");
|
||||
break;
|
||||
case Highlight_LessThanOrEqual:
|
||||
op = QStringLiteral("lessThanOrEqual");
|
||||
break;
|
||||
case Highlight_NotBetween:
|
||||
op = QStringLiteral("notBetween");
|
||||
break;
|
||||
case Highlight_NotEqual:
|
||||
op = QStringLiteral("notEqual");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cfRule->attrs[XlsxCfRuleData::A_operator] = op;
|
||||
} else if (type >= Highlight_ContainsText && type <= Highlight_EndsWith) {
|
||||
if (type == Highlight_ContainsText) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsText");
|
||||
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("containsText");
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] =
|
||||
QStringLiteral("NOT(ISERROR(SEARCH(\"%1\",%2)))").arg(formula1);
|
||||
} else if (type == Highlight_NotContainsText) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsText");
|
||||
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("notContains");
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] =
|
||||
QStringLiteral("ISERROR(SEARCH(\"%2\",%1))").arg(formula1);
|
||||
} else if (type == Highlight_BeginsWith) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("beginsWith");
|
||||
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("beginsWith");
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] =
|
||||
QStringLiteral("LEFT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1);
|
||||
} else {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("endsWith");
|
||||
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("endsWith");
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] =
|
||||
QStringLiteral("RIGHT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1);
|
||||
}
|
||||
cfRule->attrs[XlsxCfRuleData::A_text] = formula1;
|
||||
skipFormula = true;
|
||||
} else if (type == Highlight_TimePeriod) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("timePeriod");
|
||||
//: Todo
|
||||
return false;
|
||||
} else if (type == Highlight_Duplicate) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("duplicateValues");
|
||||
} else if (type == Highlight_Unique) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("uniqueValues");
|
||||
} else if (type == Highlight_Errors) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsErrors");
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("ISERROR(%1)");
|
||||
skipFormula = true;
|
||||
} else if (type == Highlight_NoErrors) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsErrors");
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(%1))");
|
||||
skipFormula = true;
|
||||
} else if (type == Highlight_Blanks) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsBlanks");
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))=0");
|
||||
skipFormula = true;
|
||||
} else if (type == Highlight_NoBlanks) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsBlanks");
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))>0");
|
||||
skipFormula = true;
|
||||
} else if (type >= Highlight_Top && type <= Highlight_BottomPercent) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("top10");
|
||||
if (type == Highlight_Bottom || type == Highlight_BottomPercent)
|
||||
cfRule->attrs[XlsxCfRuleData::A_bottom] = QStringLiteral("1");
|
||||
if (type == Highlight_TopPercent || type == Highlight_BottomPercent)
|
||||
cfRule->attrs[XlsxCfRuleData::A_percent] = QStringLiteral("1");
|
||||
cfRule->attrs[XlsxCfRuleData::A_rank] =
|
||||
!formula1.isEmpty() ? formula1 : QStringLiteral("10");
|
||||
skipFormula = true;
|
||||
} else if (type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("aboveAverage");
|
||||
if (type >= Highlight_BelowAverage && type <= Highlight_BelowStdDev3)
|
||||
cfRule->attrs[XlsxCfRuleData::A_aboveAverage] = QStringLiteral("0");
|
||||
if (type == Highlight_AboveOrEqualAverage || type == Highlight_BelowOrEqualAverage)
|
||||
cfRule->attrs[XlsxCfRuleData::A_equalAverage] = QStringLiteral("1");
|
||||
if (type == Highlight_AboveStdDev1 || type == Highlight_BelowStdDev1)
|
||||
cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("1");
|
||||
else if (type == Highlight_AboveStdDev2 || type == Highlight_BelowStdDev2)
|
||||
cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("2");
|
||||
else if (type == Highlight_AboveStdDev3 || type == Highlight_BelowStdDev3)
|
||||
cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("3");
|
||||
} else if (type == Highlight_Expression) {
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("expression");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
cfRule->dxfFormat = format;
|
||||
if (stopIfTrue)
|
||||
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true;
|
||||
if (!skipFormula) {
|
||||
if (!formula1.isEmpty())
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula1] =
|
||||
formula1.startsWith(QLatin1String("=")) ? formula1.mid(1) : formula1;
|
||||
if (!formula2.isEmpty())
|
||||
cfRule->attrs[XlsxCfRuleData::A_formula2] =
|
||||
formula2.startsWith(QLatin1String("=")) ? formula2.mid(1) : formula2;
|
||||
}
|
||||
d->cfRules.append(cfRule);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \overload
|
||||
*
|
||||
* Add a highlight rule with the given \a type \a format and \a stopIfTrue.
|
||||
*/
|
||||
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type,
|
||||
const Format &format,
|
||||
bool stopIfTrue)
|
||||
{
|
||||
if ((type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3) ||
|
||||
(type >= Highlight_Duplicate && type <= Highlight_NoErrors)) {
|
||||
return addHighlightCellsRule(type, QString(), QString(), format, stopIfTrue);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \overload
|
||||
*
|
||||
* Add a highlight rule with the given \a type, \a formula, \a format and \a stopIfTrue.
|
||||
* Return false if failed.
|
||||
*/
|
||||
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type,
|
||||
const QString &formula,
|
||||
const Format &format,
|
||||
bool stopIfTrue)
|
||||
{
|
||||
if (type == Highlight_Between || type == Highlight_NotBetween)
|
||||
return false;
|
||||
|
||||
return addHighlightCellsRule(type, formula, QString(), format, stopIfTrue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add a dataBar rule with the given \a color, \a type1, \a val1
|
||||
* , \a type2, \a val2, \a showData and \a stopIfTrue.
|
||||
* Return false if failed.
|
||||
*/
|
||||
bool ConditionalFormatting::addDataBarRule(const QColor &color,
|
||||
ValueObjectType type1,
|
||||
const QString &val1,
|
||||
ValueObjectType type2,
|
||||
const QString &val2,
|
||||
bool showData,
|
||||
bool stopIfTrue)
|
||||
{
|
||||
auto cfRule = std::make_shared<XlsxCfRuleData>();
|
||||
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("dataBar");
|
||||
cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(color);
|
||||
if (stopIfTrue)
|
||||
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true;
|
||||
if (!showData)
|
||||
cfRule->attrs[XlsxCfRuleData::A_hideData] = true;
|
||||
|
||||
XlsxCfVoData cfvo1(type1, val1);
|
||||
XlsxCfVoData cfvo2(type2, val2);
|
||||
cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1);
|
||||
cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2);
|
||||
|
||||
d->cfRules.append(cfRule);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \overload
|
||||
* Add a dataBar rule with the given \a color, \a showData and \a stopIfTrue.
|
||||
*/
|
||||
bool ConditionalFormatting::addDataBarRule(const QColor &color, bool showData, bool stopIfTrue)
|
||||
{
|
||||
return addDataBarRule(
|
||||
color, VOT_Min, QStringLiteral("0"), VOT_Max, QStringLiteral("0"), showData, stopIfTrue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add a colorScale rule with the given \a minColor, \a maxColor and \a stopIfTrue.
|
||||
* Return false if failed.
|
||||
*/
|
||||
bool ConditionalFormatting::add2ColorScaleRule(const QColor &minColor,
|
||||
const QColor &maxColor,
|
||||
bool stopIfTrue)
|
||||
{
|
||||
ValueObjectType type1 = VOT_Min;
|
||||
ValueObjectType type2 = VOT_Max;
|
||||
QString val1 = QStringLiteral("0");
|
||||
QString val2 = QStringLiteral("0");
|
||||
|
||||
auto cfRule = std::make_shared<XlsxCfRuleData>();
|
||||
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale");
|
||||
cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor);
|
||||
cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(maxColor);
|
||||
if (stopIfTrue)
|
||||
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true;
|
||||
|
||||
XlsxCfVoData cfvo1(type1, val1);
|
||||
XlsxCfVoData cfvo2(type2, val2);
|
||||
cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1);
|
||||
cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2);
|
||||
|
||||
d->cfRules.append(cfRule);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add a colorScale rule with the given \a minColor, \a midColor, \a maxColor and \a stopIfTrue.
|
||||
* Return false if failed.
|
||||
*/
|
||||
bool ConditionalFormatting::add3ColorScaleRule(const QColor &minColor,
|
||||
const QColor &midColor,
|
||||
const QColor &maxColor,
|
||||
bool stopIfTrue)
|
||||
{
|
||||
ValueObjectType type1 = VOT_Min;
|
||||
ValueObjectType type2 = VOT_Percent;
|
||||
ValueObjectType type3 = VOT_Max;
|
||||
QString val1 = QStringLiteral("0");
|
||||
QString val2 = QStringLiteral("50");
|
||||
QString val3 = QStringLiteral("0");
|
||||
|
||||
auto cfRule = std::make_shared<XlsxCfRuleData>();
|
||||
|
||||
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale");
|
||||
cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor);
|
||||
cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(midColor);
|
||||
cfRule->attrs[XlsxCfRuleData::A_color3] = XlsxColor(maxColor);
|
||||
|
||||
if (stopIfTrue)
|
||||
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true;
|
||||
|
||||
XlsxCfVoData cfvo1(type1, val1);
|
||||
XlsxCfVoData cfvo2(type2, val2);
|
||||
XlsxCfVoData cfvo3(type3, val3);
|
||||
cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1);
|
||||
cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2);
|
||||
cfRule->attrs[XlsxCfRuleData::A_cfvo3] = QVariant::fromValue(cfvo3);
|
||||
|
||||
d->cfRules.append(cfRule);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the ranges on which the validation will be applied.
|
||||
*/
|
||||
QList<CellRange> ConditionalFormatting::ranges() const
|
||||
{
|
||||
return d->ranges;
|
||||
}
|
||||
|
||||
/*!
|
||||
Add the \a cell on which the conditional formatting will apply to.
|
||||
*/
|
||||
void ConditionalFormatting::addCell(const CellReference &cell)
|
||||
{
|
||||
d->ranges.append(CellRange(cell, cell));
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Add the cell(\a row, \a col) on which the conditional formatting will apply to.
|
||||
*/
|
||||
void ConditionalFormatting::addCell(int row, int col)
|
||||
{
|
||||
d->ranges.append(CellRange(row, col, row, col));
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on
|
||||
which the conditional formatting will apply to.
|
||||
*/
|
||||
void ConditionalFormatting::addRange(int firstRow, int firstCol, int lastRow, int lastCol)
|
||||
{
|
||||
d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol));
|
||||
}
|
||||
|
||||
/*!
|
||||
Add the \a range on which the conditional formatting will apply to.
|
||||
*/
|
||||
void ConditionalFormatting::addRange(const CellRange &range)
|
||||
{
|
||||
d->ranges.append(range);
|
||||
}
|
||||
|
||||
bool ConditionalFormattingPrivate::readCfRule(QXmlStreamReader &reader,
|
||||
XlsxCfRuleData *rule,
|
||||
Styles *styles)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("cfRule"));
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
if (attrs.hasAttribute(QLatin1String("type")))
|
||||
rule->attrs[XlsxCfRuleData::A_type] = attrs.value(QLatin1String("type")).toString();
|
||||
if (attrs.hasAttribute(QLatin1String("dxfId"))) {
|
||||
int id = attrs.value(QLatin1String("dxfId")).toInt();
|
||||
if (styles)
|
||||
rule->dxfFormat = styles->dxfFormat(id);
|
||||
else
|
||||
rule->dxfFormat.setDxfIndex(id);
|
||||
}
|
||||
rule->priority = attrs.value(QLatin1String("priority")).toInt();
|
||||
if (attrs.value(QLatin1String("stopIfTrue")) == QLatin1String("1")) {
|
||||
// default is false
|
||||
rule->attrs[XlsxCfRuleData::A_stopIfTrue] = QLatin1String("1");
|
||||
}
|
||||
if (attrs.value(QLatin1String("aboveAverage")) == QLatin1String("0")) {
|
||||
// default is true
|
||||
rule->attrs[XlsxCfRuleData::A_aboveAverage] = QLatin1String("0");
|
||||
}
|
||||
if (attrs.value(QLatin1String("percent")) == QLatin1String("1")) {
|
||||
// default is false
|
||||
rule->attrs[XlsxCfRuleData::A_percent] = QLatin1String("1");
|
||||
}
|
||||
if (attrs.value(QLatin1String("bottom")) == QLatin1String("1")) {
|
||||
// default is false
|
||||
rule->attrs[XlsxCfRuleData::A_bottom] = QLatin1String("1");
|
||||
}
|
||||
if (attrs.hasAttribute(QLatin1String("operator")))
|
||||
rule->attrs[XlsxCfRuleData::A_operator] = attrs.value(QLatin1String("operator")).toString();
|
||||
|
||||
if (attrs.hasAttribute(QLatin1String("text")))
|
||||
rule->attrs[XlsxCfRuleData::A_text] = attrs.value(QLatin1String("text")).toString();
|
||||
|
||||
if (attrs.hasAttribute(QLatin1String("timePeriod")))
|
||||
rule->attrs[XlsxCfRuleData::A_timePeriod] =
|
||||
attrs.value(QLatin1String("timePeriod")).toString();
|
||||
|
||||
if (attrs.hasAttribute(QLatin1String("rank")))
|
||||
rule->attrs[XlsxCfRuleData::A_rank] = attrs.value(QLatin1String("rank")).toString();
|
||||
|
||||
if (attrs.hasAttribute(QLatin1String("stdDev")))
|
||||
rule->attrs[XlsxCfRuleData::A_stdDev] = attrs.value(QLatin1String("stdDev")).toString();
|
||||
|
||||
if (attrs.value(QLatin1String("equalAverage")) == QLatin1String("1")) {
|
||||
// default is false
|
||||
rule->attrs[XlsxCfRuleData::A_equalAverage] = QLatin1String("1");
|
||||
}
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("formula")) {
|
||||
const QString f = reader.readElementText();
|
||||
if (!rule->attrs.contains(XlsxCfRuleData::A_formula1))
|
||||
rule->attrs[XlsxCfRuleData::A_formula1] = f;
|
||||
else if (!rule->attrs.contains(XlsxCfRuleData::A_formula2))
|
||||
rule->attrs[XlsxCfRuleData::A_formula2] = f;
|
||||
else if (!rule->attrs.contains(XlsxCfRuleData::A_formula3))
|
||||
rule->attrs[XlsxCfRuleData::A_formula3] = f;
|
||||
} else if (reader.name() == QLatin1String("dataBar")) {
|
||||
readCfDataBar(reader, rule);
|
||||
} else if (reader.name() == QLatin1String("colorScale")) {
|
||||
readCfColorScale(reader, rule);
|
||||
}
|
||||
}
|
||||
if (reader.tokenType() == QXmlStreamReader::EndElement &&
|
||||
reader.name() == QStringLiteral("conditionalFormatting")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConditionalFormattingPrivate::readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *rule)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("dataBar"));
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
if (attrs.value(QLatin1String("showValue")) == QLatin1String("0"))
|
||||
rule->attrs[XlsxCfRuleData::A_hideData] = QStringLiteral("1");
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("cfvo")) {
|
||||
XlsxCfVoData data;
|
||||
readCfVo(reader, data);
|
||||
if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1))
|
||||
rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data);
|
||||
else
|
||||
rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data);
|
||||
} else if (reader.name() == QLatin1String("color")) {
|
||||
XlsxColor color;
|
||||
color.loadFromXml(reader);
|
||||
rule->attrs[XlsxCfRuleData::A_color1] = color;
|
||||
}
|
||||
}
|
||||
if (reader.tokenType() == QXmlStreamReader::EndElement &&
|
||||
reader.name() == QStringLiteral("dataBar")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConditionalFormattingPrivate::readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *rule)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("colorScale"));
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("cfvo")) {
|
||||
XlsxCfVoData data;
|
||||
readCfVo(reader, data);
|
||||
if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1))
|
||||
rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data);
|
||||
else if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo2))
|
||||
rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data);
|
||||
else
|
||||
rule->attrs[XlsxCfRuleData::A_cfvo3] = QVariant::fromValue(data);
|
||||
} else if (reader.name() == QLatin1String("color")) {
|
||||
XlsxColor color;
|
||||
color.loadFromXml(reader);
|
||||
if (!rule->attrs.contains(XlsxCfRuleData::A_color1))
|
||||
rule->attrs[XlsxCfRuleData::A_color1] = color;
|
||||
else if (!rule->attrs.contains(XlsxCfRuleData::A_color2))
|
||||
rule->attrs[XlsxCfRuleData::A_color2] = color;
|
||||
else
|
||||
rule->attrs[XlsxCfRuleData::A_color3] = color;
|
||||
}
|
||||
}
|
||||
if (reader.tokenType() == QXmlStreamReader::EndElement &&
|
||||
reader.name() == QStringLiteral("colorScale")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConditionalFormattingPrivate::readCfVo(QXmlStreamReader &reader, XlsxCfVoData &cfvo)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QStringLiteral("cfvo"));
|
||||
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
|
||||
QString type = attrs.value(QLatin1String("type")).toString();
|
||||
ConditionalFormatting::ValueObjectType t;
|
||||
if (type == QLatin1String("formula"))
|
||||
t = ConditionalFormatting::VOT_Formula;
|
||||
else if (type == QLatin1String("max"))
|
||||
t = ConditionalFormatting::VOT_Max;
|
||||
else if (type == QLatin1String("min"))
|
||||
t = ConditionalFormatting::VOT_Min;
|
||||
else if (type == QLatin1String("num"))
|
||||
t = ConditionalFormatting::VOT_Num;
|
||||
else if (type == QLatin1String("percent"))
|
||||
t = ConditionalFormatting::VOT_Percent;
|
||||
else // if (type == QLatin1String("percentile"))
|
||||
t = ConditionalFormatting::VOT_Percentile;
|
||||
|
||||
cfvo.type = t;
|
||||
cfvo.value = attrs.value(QLatin1String("val")).toString();
|
||||
if (attrs.value(QLatin1String("gte")) == QLatin1String("0")) {
|
||||
// default is true
|
||||
cfvo.gte = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConditionalFormatting::loadFromXml(QXmlStreamReader &reader, Styles *styles)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QStringLiteral("conditionalFormatting"));
|
||||
|
||||
d->ranges.clear();
|
||||
d->cfRules.clear();
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
const QString sqref = attrs.value(QLatin1String("sqref")).toString();
|
||||
const auto sqrefParts = sqref.split(QLatin1Char(' '));
|
||||
for (const QString &range : sqrefParts) {
|
||||
this->addRange(range);
|
||||
}
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("cfRule")) {
|
||||
auto cfRule = std::make_shared<XlsxCfRuleData>();
|
||||
d->readCfRule(reader, cfRule.get(), styles);
|
||||
d->cfRules.append(cfRule);
|
||||
}
|
||||
}
|
||||
if (reader.tokenType() == QXmlStreamReader::EndElement &&
|
||||
reader.name() == QStringLiteral("conditionalFormatting")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConditionalFormatting::saveToXml(QXmlStreamWriter &writer) const
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("conditionalFormatting"));
|
||||
QStringList sqref;
|
||||
const auto rangeList = ranges();
|
||||
for (const CellRange &range : rangeList) {
|
||||
sqref.append(range.toString());
|
||||
}
|
||||
writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1String(" ")));
|
||||
|
||||
for (int i = 0; i < d->cfRules.size(); ++i) {
|
||||
const std::shared_ptr<XlsxCfRuleData> &rule = d->cfRules[i];
|
||||
writer.writeStartElement(QStringLiteral("cfRule"));
|
||||
writer.writeAttribute(QStringLiteral("type"),
|
||||
rule->attrs[XlsxCfRuleData::A_type].toString());
|
||||
if (rule->dxfFormat.dxfIndexValid())
|
||||
writer.writeAttribute(QStringLiteral("dxfId"),
|
||||
QString::number(rule->dxfFormat.dxfIndex()));
|
||||
writer.writeAttribute(QStringLiteral("priority"), QString::number(rule->priority));
|
||||
|
||||
auto it = rule->attrs.constFind(XlsxCfRuleData::A_stopIfTrue);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("stopIfTrue"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_aboveAverage);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("aboveAverage"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_percent);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("percent"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_bottom);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("bottom"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_operator);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("operator"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_text);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("text"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_timePeriod);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("timePeriod"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_rank);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("rank"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_stdDev);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("stdDev"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_equalAverage);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeAttribute(QStringLiteral("equalAverage"), it.value().toString());
|
||||
|
||||
if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("dataBar")) {
|
||||
writer.writeStartElement(QStringLiteral("dataBar"));
|
||||
if (rule->attrs.contains(XlsxCfRuleData::A_hideData))
|
||||
writer.writeAttribute(QStringLiteral("showValue"), QStringLiteral("0"));
|
||||
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value<XlsxCfVoData>());
|
||||
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value<XlsxCfVoData>());
|
||||
rule->attrs[XlsxCfRuleData::A_color1].value<XlsxColor>().saveToXml(writer);
|
||||
writer.writeEndElement(); // dataBar
|
||||
} else if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("colorScale")) {
|
||||
writer.writeStartElement(QStringLiteral("colorScale"));
|
||||
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value<XlsxCfVoData>());
|
||||
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value<XlsxCfVoData>());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_cfvo3);
|
||||
if (it != rule->attrs.constEnd())
|
||||
d->writeCfVo(writer, it.value().value<XlsxCfVoData>());
|
||||
|
||||
rule->attrs[XlsxCfRuleData::A_color1].value<XlsxColor>().saveToXml(writer);
|
||||
rule->attrs[XlsxCfRuleData::A_color2].value<XlsxColor>().saveToXml(writer);
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_color3);
|
||||
if (it != rule->attrs.constEnd())
|
||||
it.value().value<XlsxColor>().saveToXml(writer);
|
||||
|
||||
writer.writeEndElement(); // colorScale
|
||||
}
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_formula1_temp);
|
||||
if (it != rule->attrs.constEnd()) {
|
||||
const auto _ranges = ranges();
|
||||
const auto begin = _ranges.begin();
|
||||
if (begin != _ranges.end()) {
|
||||
QString str = begin->toString();
|
||||
QString startCell = str.mid(0, str.indexOf(u':'));
|
||||
writer.writeTextElement(QStringLiteral("formula"),
|
||||
it.value().toString().arg(startCell));
|
||||
}
|
||||
} else {
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_formula1);
|
||||
if (it != rule->attrs.constEnd()) {
|
||||
writer.writeTextElement(QStringLiteral("formula"), it.value().toString());
|
||||
}
|
||||
}
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_formula2);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeTextElement(QStringLiteral("formula"), it.value().toString());
|
||||
|
||||
it = rule->attrs.constFind(XlsxCfRuleData::A_formula3);
|
||||
if (it != rule->attrs.constEnd())
|
||||
writer.writeTextElement(QStringLiteral("formula"), it.value().toString());
|
||||
|
||||
writer.writeEndElement(); // cfRule
|
||||
}
|
||||
|
||||
writer.writeEndElement(); // conditionalFormatting
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,200 @@
|
|||
// xlsxcontenttypes.cpp
|
||||
|
||||
#include "xlsxcontenttypes_p.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QMapIterator>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
ContentTypes::ContentTypes(CreateFlag flag)
|
||||
: AbstractOOXmlFile(flag)
|
||||
{
|
||||
m_package_prefix = QStringLiteral("application/vnd.openxmlformats-package.");
|
||||
m_document_prefix = QStringLiteral("application/vnd.openxmlformats-officedocument.");
|
||||
|
||||
m_defaults.insert(QStringLiteral("rels"),
|
||||
m_package_prefix + QLatin1String("relationships+xml"));
|
||||
m_defaults.insert(QStringLiteral("xml"), QStringLiteral("application/xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addDefault(const QString &key, const QString &value)
|
||||
{
|
||||
m_defaults.insert(key, value);
|
||||
}
|
||||
|
||||
void ContentTypes::addOverride(const QString &key, const QString &value)
|
||||
{
|
||||
m_overrides.insert(key, value);
|
||||
}
|
||||
|
||||
void ContentTypes::addDocPropApp()
|
||||
{
|
||||
addOverride(QStringLiteral("/docProps/app.xml"),
|
||||
m_document_prefix + QLatin1String("extended-properties+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addDocPropCore()
|
||||
{
|
||||
addOverride(QStringLiteral("/docProps/core.xml"),
|
||||
m_package_prefix + QLatin1String("core-properties+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addStyles()
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/styles.xml"),
|
||||
m_document_prefix + QLatin1String("spreadsheetml.styles+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addTheme()
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/theme/theme1.xml"),
|
||||
m_document_prefix + QLatin1String("theme+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addWorkbook()
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/workbook.xml"),
|
||||
m_document_prefix + QLatin1String("spreadsheetml.sheet.main+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addWorksheetName(const QString &name)
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/worksheets/%1.xml").arg(name),
|
||||
m_document_prefix + QLatin1String("spreadsheetml.worksheet+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addChartsheetName(const QString &name)
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/chartsheets/%1.xml").arg(name),
|
||||
m_document_prefix + QLatin1String("spreadsheetml.chartsheet+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addDrawingName(const QString &name)
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/drawings/%1.xml").arg(name),
|
||||
m_document_prefix + QLatin1String("drawing+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addChartName(const QString &name)
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/charts/%1.xml").arg(name),
|
||||
m_document_prefix + QLatin1String("drawingml.chart+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addCommentName(const QString &name)
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/%1.xml").arg(name),
|
||||
m_document_prefix + QLatin1String("spreadsheetml.comments+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addTableName(const QString &name)
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/tables/%1.xml").arg(name),
|
||||
m_document_prefix + QLatin1String("spreadsheetml.table+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addExternalLinkName(const QString &name)
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/externalLinks/%1.xml").arg(name),
|
||||
m_document_prefix + QLatin1String("spreadsheetml.externalLink+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addSharedString()
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/sharedStrings.xml"),
|
||||
m_document_prefix + QLatin1String("spreadsheetml.sharedStrings+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addVmlName()
|
||||
{
|
||||
addOverride(QStringLiteral("vml"), m_document_prefix + QLatin1String("vmlDrawing"));
|
||||
}
|
||||
|
||||
void ContentTypes::addCalcChain()
|
||||
{
|
||||
addOverride(QStringLiteral("/xl/calcChain.xml"),
|
||||
m_document_prefix + QLatin1String("spreadsheetml.calcChain+xml"));
|
||||
}
|
||||
|
||||
void ContentTypes::addVbaProject()
|
||||
{
|
||||
//: TODO
|
||||
addOverride(QStringLiteral("bin"), QStringLiteral("application/vnd.ms-office.vbaProject"));
|
||||
}
|
||||
|
||||
void ContentTypes::clearOverrides()
|
||||
{
|
||||
m_overrides.clear();
|
||||
}
|
||||
|
||||
void ContentTypes::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
QXmlStreamWriter writer(device);
|
||||
|
||||
writer.writeStartDocument(QStringLiteral("1.0"), true);
|
||||
writer.writeStartElement(QStringLiteral("Types"));
|
||||
writer.writeAttribute(
|
||||
QStringLiteral("xmlns"),
|
||||
QStringLiteral("http://schemas.openxmlformats.org/package/2006/content-types"));
|
||||
|
||||
{
|
||||
QMapIterator<QString, QString> it(m_defaults);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
writer.writeStartElement(QStringLiteral("Default"));
|
||||
writer.writeAttribute(QStringLiteral("Extension"), it.key());
|
||||
writer.writeAttribute(QStringLiteral("ContentType"), it.value());
|
||||
writer.writeEndElement(); // Default
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QMapIterator<QString, QString> it(m_overrides);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
writer.writeStartElement(QStringLiteral("Override"));
|
||||
writer.writeAttribute(QStringLiteral("PartName"), it.key());
|
||||
writer.writeAttribute(QStringLiteral("ContentType"), it.value());
|
||||
writer.writeEndElement(); // Override
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeEndElement(); // Types
|
||||
writer.writeEndDocument();
|
||||
}
|
||||
|
||||
bool ContentTypes::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
m_defaults.clear();
|
||||
m_overrides.clear();
|
||||
|
||||
QXmlStreamReader reader(device);
|
||||
while (!reader.atEnd()) {
|
||||
QXmlStreamReader::TokenType token = reader.readNext();
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("Default")) {
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
QString extension = attrs.value(QLatin1String("Extension")).toString();
|
||||
QString type = attrs.value(QLatin1String("ContentType")).toString();
|
||||
m_defaults.insert(extension, type);
|
||||
} else if (reader.name() == QLatin1String("Override")) {
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
QString partName = attrs.value(QLatin1String("PartName")).toString();
|
||||
QString type = attrs.value(QLatin1String("ContentType")).toString();
|
||||
m_overrides.insert(partName, type);
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.hasError()) {
|
||||
qDebug() << reader.errorString();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,548 @@
|
|||
// xlsxdatavalidation.cpp
|
||||
|
||||
#include "xlsxdatavalidation.h"
|
||||
|
||||
#include "xlsxcellrange.h"
|
||||
#include "xlsxdatavalidation_p.h"
|
||||
#include "xlsxworksheet.h"
|
||||
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
DataValidationPrivate::DataValidationPrivate()
|
||||
: validationType(DataValidation::None)
|
||||
, validationOperator(DataValidation::Between)
|
||||
, errorStyle(DataValidation::Stop)
|
||||
, allowBlank(false)
|
||||
, isPromptMessageVisible(true)
|
||||
, isErrorMessageVisible(true)
|
||||
{
|
||||
}
|
||||
|
||||
DataValidationPrivate::DataValidationPrivate(DataValidation::ValidationType type,
|
||||
DataValidation::ValidationOperator op,
|
||||
const QString &formula1,
|
||||
const QString &formula2,
|
||||
bool allowBlank)
|
||||
: validationType(type)
|
||||
, validationOperator(op)
|
||||
, errorStyle(DataValidation::Stop)
|
||||
, allowBlank(allowBlank)
|
||||
, isPromptMessageVisible(true)
|
||||
, isErrorMessageVisible(true)
|
||||
, formula1(formula1)
|
||||
, formula2(formula2)
|
||||
{
|
||||
}
|
||||
|
||||
DataValidationPrivate::DataValidationPrivate(const DataValidationPrivate &other)
|
||||
: QSharedData(other)
|
||||
, validationType(DataValidation::None)
|
||||
, validationOperator(DataValidation::Between)
|
||||
, errorStyle(DataValidation::Stop)
|
||||
, allowBlank(false)
|
||||
, isPromptMessageVisible(true)
|
||||
, isErrorMessageVisible(true)
|
||||
{
|
||||
}
|
||||
|
||||
DataValidationPrivate::~DataValidationPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \class DataValidation
|
||||
* \brief Data validation for single cell or a range
|
||||
* \inmodule QtXlsx
|
||||
*
|
||||
* The data validation can be applied to a single cell or a range of cells.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \enum DataValidation::ValidationType
|
||||
*
|
||||
* The enum type defines the type of data that you wish to validate.
|
||||
*
|
||||
* \value None the type of data is unrestricted. This is the same as not applying a data validation.
|
||||
* \value Whole restricts the cell to integer values. Means "Whole number"?
|
||||
* \value Decimal restricts the cell to decimal values.
|
||||
* \value List restricts the cell to a set of user specified values.
|
||||
* \value Date restricts the cell to date values.
|
||||
* \value Time restricts the cell to time values.
|
||||
* \value TextLength restricts the cell data based on an integer string length.
|
||||
* \value Custom restricts the cell based on an external Excel formula that returns a true/false
|
||||
* value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \enum DataValidation::ValidationOperator
|
||||
*
|
||||
* The enum type defines the criteria by which the data in the
|
||||
* cell is validated
|
||||
*
|
||||
* \value Between
|
||||
* \value NotBetween
|
||||
* \value Equal
|
||||
* \value NotEqual
|
||||
* \value LessThan
|
||||
* \value LessThanOrEqual
|
||||
* \value GreaterThan
|
||||
* \value GreaterThanOrEqual
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \enum DataValidation::ErrorStyle
|
||||
*
|
||||
* The enum type defines the type of error dialog that
|
||||
* is displayed.
|
||||
*
|
||||
* \value Stop
|
||||
* \value Warning
|
||||
* \value Information
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Construct a data validation object with the given \a type, \a op, \a formula1
|
||||
* \a formula2, and \a allowBlank.
|
||||
*/
|
||||
DataValidation::DataValidation(ValidationType type,
|
||||
ValidationOperator op,
|
||||
const QString &formula1,
|
||||
const QString &formula2,
|
||||
bool allowBlank)
|
||||
: d(new DataValidationPrivate(type, op, formula1, formula2, allowBlank))
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Construct a data validation object
|
||||
*/
|
||||
DataValidation::DataValidation()
|
||||
: d(new DataValidationPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a copy of \a other.
|
||||
*/
|
||||
DataValidation::DataValidation(const DataValidation &other)
|
||||
: d(other.d)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Assigns \a other to this validation and returns a reference to this validation.
|
||||
*/
|
||||
DataValidation &DataValidation::operator=(const DataValidation &other)
|
||||
{
|
||||
if (this != &other) // Self-assignment check [cert-oop54-cpp]
|
||||
{
|
||||
this->d = other.d;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Destroy the object.
|
||||
*/
|
||||
DataValidation::~DataValidation()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the validation type.
|
||||
*/
|
||||
DataValidation::ValidationType DataValidation::validationType() const
|
||||
{
|
||||
return d->validationType;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the validation operator.
|
||||
*/
|
||||
DataValidation::ValidationOperator DataValidation::validationOperator() const
|
||||
{
|
||||
return d->validationOperator;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the validation error style.
|
||||
*/
|
||||
DataValidation::ErrorStyle DataValidation::errorStyle() const
|
||||
{
|
||||
return d->errorStyle;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the formula1.
|
||||
*/
|
||||
QString DataValidation::formula1() const
|
||||
{
|
||||
return d->formula1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the formula2.
|
||||
*/
|
||||
QString DataValidation::formula2() const
|
||||
{
|
||||
return d->formula2;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns whether blank is allowed.
|
||||
*/
|
||||
bool DataValidation::allowBlank() const
|
||||
{
|
||||
return d->allowBlank;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the error message.
|
||||
*/
|
||||
QString DataValidation::errorMessage() const
|
||||
{
|
||||
return d->errorMessage;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the error message title.
|
||||
*/
|
||||
QString DataValidation::errorMessageTitle() const
|
||||
{
|
||||
return d->errorMessageTitle;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the prompt message.
|
||||
*/
|
||||
QString DataValidation::promptMessage() const
|
||||
{
|
||||
return d->promptMessage;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the prompt message title.
|
||||
*/
|
||||
QString DataValidation::promptMessageTitle() const
|
||||
{
|
||||
return d->promptMessageTitle;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the whether prompt message is shown.
|
||||
*/
|
||||
bool DataValidation::isPromptMessageVisible() const
|
||||
{
|
||||
return d->isPromptMessageVisible;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the whether error message is shown.
|
||||
*/
|
||||
bool DataValidation::isErrorMessageVisible() const
|
||||
{
|
||||
return d->isErrorMessageVisible;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the ranges on which the validation will be applied.
|
||||
*/
|
||||
QList<CellRange> DataValidation::ranges() const
|
||||
{
|
||||
return d->ranges;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the validation type to \a type.
|
||||
*/
|
||||
void DataValidation::setValidationType(DataValidation::ValidationType type)
|
||||
{
|
||||
d->validationType = type;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the validation operator to \a op.
|
||||
*/
|
||||
void DataValidation::setValidationOperator(DataValidation::ValidationOperator op)
|
||||
{
|
||||
d->validationOperator = op;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the error style to \a es.
|
||||
*/
|
||||
void DataValidation::setErrorStyle(DataValidation::ErrorStyle es)
|
||||
{
|
||||
d->errorStyle = es;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the formula1 to \a formula.
|
||||
*/
|
||||
void DataValidation::setFormula1(const QString &formula)
|
||||
{
|
||||
if (formula.startsWith(QLatin1Char('=')))
|
||||
d->formula1 = formula.mid(1);
|
||||
else
|
||||
d->formula1 = formula;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the formulas to \a formula.
|
||||
*/
|
||||
void DataValidation::setFormula2(const QString &formula)
|
||||
{
|
||||
if (formula.startsWith(QLatin1Char('=')))
|
||||
d->formula2 = formula.mid(1);
|
||||
else
|
||||
d->formula2 = formula;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the error message to \a error with title \a title.
|
||||
*/
|
||||
void DataValidation::setErrorMessage(const QString &error, const QString &title)
|
||||
{
|
||||
d->errorMessage = error;
|
||||
d->errorMessageTitle = title;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the prompt message to \a prompt with title \a title.
|
||||
*/
|
||||
void DataValidation::setPromptMessage(const QString &prompt, const QString &title)
|
||||
{
|
||||
d->promptMessage = prompt;
|
||||
d->promptMessageTitle = title;
|
||||
}
|
||||
|
||||
/*!
|
||||
Enable/disable blank allow based on \a enable.
|
||||
*/
|
||||
void DataValidation::setAllowBlank(bool enable)
|
||||
{
|
||||
d->allowBlank = enable;
|
||||
}
|
||||
|
||||
/*!
|
||||
Enable/disable prompt message visible based on \a visible.
|
||||
*/
|
||||
void DataValidation::setPromptMessageVisible(bool visible)
|
||||
{
|
||||
d->isPromptMessageVisible = visible;
|
||||
}
|
||||
|
||||
/*!
|
||||
Enable/disable error message visible based on \a visible.
|
||||
*/
|
||||
void DataValidation::setErrorMessageVisible(bool visible)
|
||||
{
|
||||
d->isErrorMessageVisible = visible;
|
||||
}
|
||||
|
||||
/*!
|
||||
Add the \a cell on which the DataValidation will apply to.
|
||||
*/
|
||||
void DataValidation::addCell(const CellReference &cell)
|
||||
{
|
||||
d->ranges.append(CellRange(cell, cell));
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Add the cell(\a row, \a col) on which the DataValidation will apply to.
|
||||
*/
|
||||
void DataValidation::addCell(int row, int col)
|
||||
{
|
||||
d->ranges.append(CellRange(row, col, row, col));
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on
|
||||
which the DataValidation will apply to.
|
||||
*/
|
||||
void DataValidation::addRange(int firstRow, int firstCol, int lastRow, int lastCol)
|
||||
{
|
||||
d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol));
|
||||
}
|
||||
|
||||
/*!
|
||||
Add the \a range on which the DataValidation will apply to.
|
||||
*/
|
||||
void DataValidation::addRange(const CellRange &range)
|
||||
{
|
||||
d->ranges.append(range);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
bool DataValidation::saveToXml(QXmlStreamWriter &writer) const
|
||||
{
|
||||
static const QMap<DataValidation::ValidationType, QString> typeMap = {
|
||||
{DataValidation::None, QStringLiteral("none")},
|
||||
{DataValidation::Whole, QStringLiteral("whole")},
|
||||
{DataValidation::Decimal, QStringLiteral("decimal")},
|
||||
{DataValidation::List, QStringLiteral("list")},
|
||||
{DataValidation::Date, QStringLiteral("date")},
|
||||
{DataValidation::Time, QStringLiteral("time")},
|
||||
{DataValidation::TextLength, QStringLiteral("textLength")},
|
||||
{DataValidation::Custom, QStringLiteral("custom")}};
|
||||
|
||||
static const QMap<DataValidation::ValidationOperator, QString> opMap = {
|
||||
{DataValidation::Between, QStringLiteral("between")},
|
||||
{DataValidation::NotBetween, QStringLiteral("notBetween")},
|
||||
{DataValidation::Equal, QStringLiteral("equal")},
|
||||
{DataValidation::NotEqual, QStringLiteral("notEqual")},
|
||||
{DataValidation::LessThan, QStringLiteral("lessThan")},
|
||||
{DataValidation::LessThanOrEqual, QStringLiteral("lessThanOrEqual")},
|
||||
{DataValidation::GreaterThan, QStringLiteral("greaterThan")},
|
||||
{DataValidation::GreaterThanOrEqual, QStringLiteral("greaterThanOrEqual")}};
|
||||
|
||||
static const QMap<DataValidation::ErrorStyle, QString> esMap = {
|
||||
{DataValidation::Stop, QStringLiteral("stop")},
|
||||
{DataValidation::Warning, QStringLiteral("warning")},
|
||||
{DataValidation::Information, QStringLiteral("information")}};
|
||||
|
||||
writer.writeStartElement(QStringLiteral("dataValidation"));
|
||||
if (validationType() != DataValidation::None)
|
||||
writer.writeAttribute(QStringLiteral("type"), typeMap[validationType()]);
|
||||
if (errorStyle() != DataValidation::Stop)
|
||||
writer.writeAttribute(QStringLiteral("errorStyle"), esMap[errorStyle()]);
|
||||
if (validationOperator() != DataValidation::Between)
|
||||
writer.writeAttribute(QStringLiteral("operator"), opMap[validationOperator()]);
|
||||
if (allowBlank())
|
||||
writer.writeAttribute(QStringLiteral("allowBlank"), QStringLiteral("1"));
|
||||
// if (dropDownVisible())
|
||||
// writer.writeAttribute(QStringLiteral("showDropDown"), QStringLiteral("1"));
|
||||
if (isPromptMessageVisible())
|
||||
writer.writeAttribute(QStringLiteral("showInputMessage"), QStringLiteral("1"));
|
||||
if (isErrorMessageVisible())
|
||||
writer.writeAttribute(QStringLiteral("showErrorMessage"), QStringLiteral("1"));
|
||||
if (!errorMessageTitle().isEmpty())
|
||||
writer.writeAttribute(QStringLiteral("errorTitle"), errorMessageTitle());
|
||||
if (!errorMessage().isEmpty())
|
||||
writer.writeAttribute(QStringLiteral("error"), errorMessage());
|
||||
if (!promptMessageTitle().isEmpty())
|
||||
writer.writeAttribute(QStringLiteral("promptTitle"), promptMessageTitle());
|
||||
if (!promptMessage().isEmpty())
|
||||
writer.writeAttribute(QStringLiteral("prompt"), promptMessage());
|
||||
|
||||
QStringList sqref;
|
||||
const auto rangeList = ranges();
|
||||
for (const CellRange &range : rangeList)
|
||||
sqref.append(range.toString());
|
||||
writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1String(" ")));
|
||||
|
||||
if (!formula1().isEmpty())
|
||||
writer.writeTextElement(QStringLiteral("formula1"), formula1());
|
||||
if (!formula2().isEmpty())
|
||||
writer.writeTextElement(QStringLiteral("formula2"), formula2());
|
||||
|
||||
writer.writeEndElement(); // dataValidation
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
DataValidation DataValidation::loadFromXml(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("dataValidation"));
|
||||
|
||||
static const QMap<QString, DataValidation::ValidationType> typeMap = {
|
||||
{QStringLiteral("none"), DataValidation::None},
|
||||
{QStringLiteral("whole"), DataValidation::Whole},
|
||||
{QStringLiteral("decimal"), DataValidation::Decimal},
|
||||
{QStringLiteral("list"), DataValidation::List},
|
||||
{QStringLiteral("date"), DataValidation::Date},
|
||||
{QStringLiteral("time"), DataValidation::Time},
|
||||
{QStringLiteral("textLength"), DataValidation::TextLength},
|
||||
{QStringLiteral("custom"), DataValidation::Custom}};
|
||||
|
||||
static const QMap<QString, DataValidation::ValidationOperator> opMap = {
|
||||
{QStringLiteral("between"), DataValidation::Between},
|
||||
{QStringLiteral("notBetween"), DataValidation::NotBetween},
|
||||
{QStringLiteral("equal"), DataValidation::Equal},
|
||||
{QStringLiteral("notEqual"), DataValidation::NotEqual},
|
||||
{QStringLiteral("lessThan"), DataValidation::LessThan},
|
||||
{QStringLiteral("lessThanOrEqual"), DataValidation::LessThanOrEqual},
|
||||
{QStringLiteral("greaterThan"), DataValidation::GreaterThan},
|
||||
{QStringLiteral("greaterThanOrEqual"), DataValidation::GreaterThanOrEqual}};
|
||||
|
||||
static const QMap<QString, DataValidation::ErrorStyle> esMap = {
|
||||
{QStringLiteral("stop"), DataValidation::Stop},
|
||||
{QStringLiteral("warning"), DataValidation::Warning},
|
||||
{QStringLiteral("information"), DataValidation::Information}};
|
||||
|
||||
DataValidation validation;
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
|
||||
QString sqref = attrs.value(QLatin1String("sqref")).toString();
|
||||
const auto sqrefParts = sqref.split(QLatin1Char(' '));
|
||||
for (const QString &range : sqrefParts)
|
||||
validation.addRange(range);
|
||||
|
||||
if (attrs.hasAttribute(QLatin1String("type"))) {
|
||||
QString t = attrs.value(QLatin1String("type")).toString();
|
||||
auto it = typeMap.constFind(t);
|
||||
validation.setValidationType(it != typeMap.constEnd() ? it.value() : DataValidation::None);
|
||||
}
|
||||
if (attrs.hasAttribute(QLatin1String("errorStyle"))) {
|
||||
QString es = attrs.value(QLatin1String("errorStyle")).toString();
|
||||
auto it = esMap.constFind(es);
|
||||
validation.setErrorStyle(it != esMap.constEnd() ? it.value() : DataValidation::Stop);
|
||||
}
|
||||
if (attrs.hasAttribute(QLatin1String("operator"))) {
|
||||
QString op = attrs.value(QLatin1String("operator")).toString();
|
||||
auto it = opMap.constFind(op);
|
||||
validation.setValidationOperator(it != opMap.constEnd() ? it.value()
|
||||
: DataValidation::Between);
|
||||
}
|
||||
if (attrs.hasAttribute(QLatin1String("allowBlank"))) {
|
||||
validation.setAllowBlank(true);
|
||||
} else {
|
||||
validation.setAllowBlank(false);
|
||||
}
|
||||
if (attrs.hasAttribute(QLatin1String("showInputMessage"))) {
|
||||
validation.setPromptMessageVisible(true);
|
||||
} else {
|
||||
validation.setPromptMessageVisible(false);
|
||||
}
|
||||
if (attrs.hasAttribute(QLatin1String("showErrorMessage"))) {
|
||||
validation.setErrorMessageVisible(true);
|
||||
} else {
|
||||
validation.setErrorMessageVisible(false);
|
||||
}
|
||||
|
||||
QString et = attrs.value(QLatin1String("errorTitle")).toString();
|
||||
QString e = attrs.value(QLatin1String("error")).toString();
|
||||
if (!e.isEmpty() || !et.isEmpty())
|
||||
validation.setErrorMessage(e, et);
|
||||
|
||||
QString pt = attrs.value(QLatin1String("promptTitle")).toString();
|
||||
QString p = attrs.value(QLatin1String("prompt")).toString();
|
||||
if (!p.isEmpty() || !pt.isEmpty())
|
||||
validation.setPromptMessage(p, pt);
|
||||
|
||||
// find the end
|
||||
while (!(reader.name() == QLatin1String("dataValidation") &&
|
||||
reader.tokenType() == QXmlStreamReader::EndElement)) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("formula1")) {
|
||||
validation.setFormula1(reader.readElementText());
|
||||
} else if (reader.name() == QLatin1String("formula2")) {
|
||||
validation.setFormula2(reader.readElementText());
|
||||
}
|
||||
}
|
||||
}
|
||||
return validation;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,84 @@
|
|||
// xlsxdatetype.cpp
|
||||
|
||||
#include "xlsxdatetype.h"
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
#include "xlsxutility_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
DateType::DateType()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
DateType::DateType(bool is1904)
|
||||
{
|
||||
isSet = false;
|
||||
}
|
||||
|
||||
DateType::DateType(double d, bool is1904)
|
||||
{
|
||||
// TODO: check date
|
||||
|
||||
// int iVaue = (int) d;
|
||||
// double surplus = d - double(iVaue);
|
||||
|
||||
dValue = d;
|
||||
is1904Type = is1904;
|
||||
isSet = true;
|
||||
}
|
||||
|
||||
DateType::DateType(QDateTime qdt, bool is1904)
|
||||
{
|
||||
double ret = datetimeToNumber( qdt, is1904 );
|
||||
dValue = ret;
|
||||
is1904Type = is1904;
|
||||
isSet = true;
|
||||
}
|
||||
|
||||
DateType::DateType(QDate qd, bool is1904)
|
||||
{
|
||||
|
||||
is1904Type = is1904;
|
||||
isSet = true;
|
||||
}
|
||||
|
||||
DateType::DateType(QTime qt, bool is1904)
|
||||
{
|
||||
double ret = timeToNumber( qt );
|
||||
dValue = ret;
|
||||
is1904Type = is1904;
|
||||
isSet = true;
|
||||
}
|
||||
|
||||
// enum currentDateType { DateAndTimeType, OnlyDateType, OnlyTimeType };
|
||||
|
||||
DateType::currentDateType DateType::getType()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool DateType::getValue(QDateTime* pQdt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool DateType::getValue(QDate* pQd)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool DateType::getValue(QTime* pQt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool DateType::getValue(double* pD)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,139 @@
|
|||
// xlsxdocpropsapp.cpp
|
||||
|
||||
#include "xlsxdocpropsapp_p.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QVariant>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
DocPropsApp::DocPropsApp(CreateFlag flag)
|
||||
: AbstractOOXmlFile(flag)
|
||||
{
|
||||
}
|
||||
|
||||
void DocPropsApp::addPartTitle(const QString &title)
|
||||
{
|
||||
m_titlesOfPartsList.append(title);
|
||||
}
|
||||
|
||||
void DocPropsApp::addHeadingPair(const QString &name, int value)
|
||||
{
|
||||
m_headingPairsList.append({name, value});
|
||||
}
|
||||
|
||||
bool DocPropsApp::setProperty(const QString &name, const QString &value)
|
||||
{
|
||||
static const QStringList validKeys = {QStringLiteral("manager"), QStringLiteral("company")};
|
||||
|
||||
if (!validKeys.contains(name))
|
||||
return false;
|
||||
|
||||
if (value.isEmpty())
|
||||
m_properties.remove(name);
|
||||
else
|
||||
m_properties[name] = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString DocPropsApp::property(const QString &name) const
|
||||
{
|
||||
auto it = m_properties.constFind(name);
|
||||
if (it != m_properties.constEnd())
|
||||
return it.value();
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList DocPropsApp::propertyNames() const
|
||||
{
|
||||
return m_properties.keys();
|
||||
}
|
||||
|
||||
void DocPropsApp::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
QXmlStreamWriter writer(device);
|
||||
QString vt =
|
||||
QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
|
||||
|
||||
writer.writeStartDocument(QStringLiteral("1.0"), true);
|
||||
writer.writeStartElement(QStringLiteral("Properties"));
|
||||
writer.writeDefaultNamespace(QStringLiteral(
|
||||
"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"));
|
||||
writer.writeNamespace(vt, QStringLiteral("vt"));
|
||||
writer.writeTextElement(QStringLiteral("Application"), QStringLiteral("Microsoft Excel"));
|
||||
writer.writeTextElement(QStringLiteral("DocSecurity"), QStringLiteral("0"));
|
||||
writer.writeTextElement(QStringLiteral("ScaleCrop"), QStringLiteral("false"));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("HeadingPairs"));
|
||||
writer.writeStartElement(vt, QStringLiteral("vector"));
|
||||
writer.writeAttribute(QStringLiteral("size"), QString::number(m_headingPairsList.size() * 2));
|
||||
writer.writeAttribute(QStringLiteral("baseType"), QStringLiteral("variant"));
|
||||
|
||||
for (const auto &pair : m_headingPairsList) {
|
||||
writer.writeStartElement(vt, QStringLiteral("variant"));
|
||||
writer.writeTextElement(vt, QStringLiteral("lpstr"), pair.first);
|
||||
writer.writeEndElement(); // vt:variant
|
||||
writer.writeStartElement(vt, QStringLiteral("variant"));
|
||||
writer.writeTextElement(vt, QStringLiteral("i4"), QString::number(pair.second));
|
||||
writer.writeEndElement(); // vt:variant
|
||||
}
|
||||
writer.writeEndElement(); // vt:vector
|
||||
writer.writeEndElement(); // HeadingPairs
|
||||
|
||||
writer.writeStartElement(QStringLiteral("TitlesOfParts"));
|
||||
writer.writeStartElement(vt, QStringLiteral("vector"));
|
||||
writer.writeAttribute(QStringLiteral("size"), QString::number(m_titlesOfPartsList.size()));
|
||||
writer.writeAttribute(QStringLiteral("baseType"), QStringLiteral("lpstr"));
|
||||
for (const QString &title : m_titlesOfPartsList)
|
||||
writer.writeTextElement(vt, QStringLiteral("lpstr"), title);
|
||||
writer.writeEndElement(); // vt:vector
|
||||
writer.writeEndElement(); // TitlesOfParts
|
||||
|
||||
auto it = m_properties.constFind(QStringLiteral("manager"));
|
||||
if (it != m_properties.constEnd())
|
||||
writer.writeTextElement(QStringLiteral("Manager"), it.value());
|
||||
// Not like "manager", "company" always exists for Excel generated file.
|
||||
|
||||
it = m_properties.constFind(QStringLiteral("company"));
|
||||
writer.writeTextElement(QStringLiteral("Company"),
|
||||
it != m_properties.constEnd() ? it.value() : QString());
|
||||
writer.writeTextElement(QStringLiteral("LinksUpToDate"), QStringLiteral("false"));
|
||||
writer.writeTextElement(QStringLiteral("SharedDoc"), QStringLiteral("false"));
|
||||
writer.writeTextElement(QStringLiteral("HyperlinksChanged"), QStringLiteral("false"));
|
||||
writer.writeTextElement(QStringLiteral("AppVersion"), QStringLiteral("12.0000"));
|
||||
|
||||
writer.writeEndElement(); // Properties
|
||||
writer.writeEndDocument();
|
||||
}
|
||||
|
||||
bool DocPropsApp::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
QXmlStreamReader reader(device);
|
||||
while (!reader.atEnd()) {
|
||||
QXmlStreamReader::TokenType token = reader.readNext();
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("Properties"))
|
||||
continue;
|
||||
|
||||
if (reader.name() == QStringLiteral("Manager")) {
|
||||
setProperty(QStringLiteral("manager"), reader.readElementText());
|
||||
} else if (reader.name() == QStringLiteral("Company")) {
|
||||
setProperty(QStringLiteral("company"), reader.readElementText());
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.hasError()) {
|
||||
qDebug("Error when read doc props app file.");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,169 @@
|
|||
// xlsxdocpropscore.cpp
|
||||
|
||||
#include "xlsxdocpropscore_p.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
DocPropsCore::DocPropsCore(CreateFlag flag)
|
||||
: AbstractOOXmlFile(flag)
|
||||
{
|
||||
}
|
||||
|
||||
bool DocPropsCore::setProperty(const QString &name, const QString &value)
|
||||
{
|
||||
static const QStringList validKeys = {QStringLiteral("title"),
|
||||
QStringLiteral("subject"),
|
||||
QStringLiteral("keywords"),
|
||||
QStringLiteral("description"),
|
||||
QStringLiteral("category"),
|
||||
QStringLiteral("status"),
|
||||
QStringLiteral("created"),
|
||||
QStringLiteral("creator")};
|
||||
|
||||
if (!validKeys.contains(name))
|
||||
return false;
|
||||
|
||||
if (value.isEmpty())
|
||||
m_properties.remove(name);
|
||||
else
|
||||
m_properties[name] = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString DocPropsCore::property(const QString &name) const
|
||||
{
|
||||
auto it = m_properties.constFind(name);
|
||||
if (it != m_properties.constEnd())
|
||||
return it.value();
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList DocPropsCore::propertyNames() const
|
||||
{
|
||||
return m_properties.keys();
|
||||
}
|
||||
|
||||
void DocPropsCore::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
QXmlStreamWriter writer(device);
|
||||
const QString cp =
|
||||
QStringLiteral("http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
|
||||
const QString dc = QStringLiteral("http://purl.org/dc/elements/1.1/");
|
||||
const QString dcterms = QStringLiteral("http://purl.org/dc/terms/");
|
||||
const QString dcmitype = QStringLiteral("http://purl.org/dc/dcmitype/");
|
||||
const QString xsi = QStringLiteral("http://www.w3.org/2001/XMLSchema-instance");
|
||||
writer.writeStartDocument(QStringLiteral("1.0"), true);
|
||||
writer.writeStartElement(QStringLiteral("cp:coreProperties"));
|
||||
writer.writeNamespace(cp, QStringLiteral("cp"));
|
||||
writer.writeNamespace(dc, QStringLiteral("dc"));
|
||||
writer.writeNamespace(dcterms, QStringLiteral("dcterms"));
|
||||
writer.writeNamespace(dcmitype, QStringLiteral("dcmitype"));
|
||||
writer.writeNamespace(xsi, QStringLiteral("xsi"));
|
||||
|
||||
auto it = m_properties.constFind(QStringLiteral("title"));
|
||||
if (it != m_properties.constEnd())
|
||||
writer.writeTextElement(dc, QStringLiteral("title"), it.value());
|
||||
|
||||
it = m_properties.constFind(QStringLiteral("subject"));
|
||||
if (it != m_properties.constEnd())
|
||||
writer.writeTextElement(dc, QStringLiteral("subject"), it.value());
|
||||
|
||||
it = m_properties.constFind(QStringLiteral("creator"));
|
||||
writer.writeTextElement(dc,
|
||||
QStringLiteral("creator"),
|
||||
it != m_properties.constEnd() ? it.value()
|
||||
: QStringLiteral("Qt Xlsx Library"));
|
||||
|
||||
it = m_properties.constFind(QStringLiteral("keywords"));
|
||||
if (it != m_properties.constEnd())
|
||||
writer.writeTextElement(cp, QStringLiteral("keywords"), it.value());
|
||||
|
||||
it = m_properties.constFind(QStringLiteral("description"));
|
||||
if (it != m_properties.constEnd())
|
||||
writer.writeTextElement(dc, QStringLiteral("description"), it.value());
|
||||
|
||||
it = m_properties.constFind(QStringLiteral("creator"));
|
||||
writer.writeTextElement(cp,
|
||||
QStringLiteral("lastModifiedBy"),
|
||||
it != m_properties.constEnd() ? it.value()
|
||||
: QStringLiteral("Qt Xlsx Library"));
|
||||
|
||||
writer.writeStartElement(dcterms, QStringLiteral("created"));
|
||||
writer.writeAttribute(xsi, QStringLiteral("type"), QStringLiteral("dcterms:W3CDTF"));
|
||||
it = m_properties.constFind(QStringLiteral("created"));
|
||||
writer.writeCharacters(it != m_properties.constEnd()
|
||||
? it.value()
|
||||
: QDateTime::currentDateTime().toString(Qt::ISODate));
|
||||
writer.writeEndElement(); // dcterms:created
|
||||
|
||||
writer.writeStartElement(dcterms, QStringLiteral("modified"));
|
||||
writer.writeAttribute(xsi, QStringLiteral("type"), QStringLiteral("dcterms:W3CDTF"));
|
||||
writer.writeCharacters(QDateTime::currentDateTime().toString(Qt::ISODate));
|
||||
writer.writeEndElement(); // dcterms:created
|
||||
|
||||
it = m_properties.constFind(QStringLiteral("category"));
|
||||
if (it != m_properties.constEnd())
|
||||
writer.writeTextElement(cp, QStringLiteral("category"), it.value());
|
||||
|
||||
it = m_properties.constFind(QStringLiteral("status"));
|
||||
if (it != m_properties.constEnd())
|
||||
writer.writeTextElement(cp, QStringLiteral("contentStatus"), it.value());
|
||||
|
||||
writer.writeEndElement(); // cp:coreProperties
|
||||
writer.writeEndDocument();
|
||||
}
|
||||
|
||||
bool DocPropsCore::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
QXmlStreamReader reader(device);
|
||||
|
||||
const QString cp =
|
||||
QStringLiteral("http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
|
||||
const QString dc = QStringLiteral("http://purl.org/dc/elements/1.1/");
|
||||
const QString dcterms = QStringLiteral("http://purl.org/dc/terms/");
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
QXmlStreamReader::TokenType token = reader.readNext();
|
||||
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
|
||||
const auto &nsUri = reader.namespaceUri();
|
||||
const auto &name = reader.name();
|
||||
|
||||
if (name == QStringLiteral("subject") && nsUri == dc) {
|
||||
setProperty(QStringLiteral("subject"), reader.readElementText());
|
||||
} else if (name == QStringLiteral("title") && nsUri == dc) {
|
||||
setProperty(QStringLiteral("title"), reader.readElementText());
|
||||
} else if (name == QStringLiteral("creator") && nsUri == dc) {
|
||||
setProperty(QStringLiteral("creator"), reader.readElementText());
|
||||
} else if (name == QStringLiteral("description") && nsUri == dc) {
|
||||
setProperty(QStringLiteral("description"), reader.readElementText());
|
||||
} else if (name == QStringLiteral("keywords") && nsUri == cp) {
|
||||
setProperty(QStringLiteral("keywords"), reader.readElementText());
|
||||
} else if (name == QStringLiteral("created") && nsUri == dcterms) {
|
||||
setProperty(QStringLiteral("created"), reader.readElementText());
|
||||
} else if (name == QStringLiteral("category") && nsUri == cp) {
|
||||
setProperty(QStringLiteral("category"), reader.readElementText());
|
||||
} else if (name == QStringLiteral("contentStatus") && nsUri == cp) {
|
||||
setProperty(QStringLiteral("status"), reader.readElementText());
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.hasError()) {
|
||||
qDebug() << "Error when read doc props core file." << reader.errorString();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,83 @@
|
|||
// xlsxdrawing.cpp
|
||||
|
||||
#include "xlsxabstractsheet.h"
|
||||
#include "xlsxdrawing_p.h"
|
||||
#include "xlsxdrawinganchor_p.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
Drawing::Drawing(AbstractSheet *sheet, CreateFlag flag)
|
||||
: AbstractOOXmlFile(flag)
|
||||
, sheet(sheet)
|
||||
{
|
||||
workbook = sheet->workbook();
|
||||
}
|
||||
|
||||
Drawing::~Drawing()
|
||||
{
|
||||
qDeleteAll(anchors);
|
||||
}
|
||||
|
||||
void Drawing::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
relationships()->clear();
|
||||
|
||||
QXmlStreamWriter writer(device);
|
||||
|
||||
writer.writeStartDocument(QStringLiteral("1.0"), true);
|
||||
writer.writeStartElement(QStringLiteral("xdr:wsDr"));
|
||||
writer.writeAttribute(
|
||||
QStringLiteral("xmlns:xdr"),
|
||||
QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"));
|
||||
writer.writeAttribute(QStringLiteral("xmlns:a"),
|
||||
QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main"));
|
||||
|
||||
for (DrawingAnchor *anchor : anchors)
|
||||
anchor->saveToXml(writer);
|
||||
|
||||
writer.writeEndElement(); // xdr:wsDr
|
||||
writer.writeEndDocument();
|
||||
}
|
||||
|
||||
// check point
|
||||
bool Drawing::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
/*
|
||||
<xsd:group name="EG_Anchor">
|
||||
<xsd:choice>
|
||||
<xsd:element name="twoCellAnchor" type="CT_TwoCellAnchor"/>
|
||||
<xsd:element name="oneCellAnchor" type="CT_OneCellAnchor"/>
|
||||
<xsd:element name="absoluteAnchor" type="CT_AbsoluteAnchor"/>
|
||||
</xsd:choice>
|
||||
</xsd:group>
|
||||
*/
|
||||
|
||||
QXmlStreamReader reader(device);
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("absoluteAnchor")) // CT_AbsoluteAnchor
|
||||
{
|
||||
auto *anchor = new DrawingAbsoluteAnchor(this);
|
||||
anchor->loadFromXml(reader);
|
||||
} else if (reader.name() == QLatin1String("oneCellAnchor")) // CT_OneCellAnchor
|
||||
{
|
||||
auto *anchor = new DrawingOneCellAnchor(this);
|
||||
anchor->loadFromXml(reader);
|
||||
} else if (reader.name() == QLatin1String("twoCellAnchor")) // CT_TwoCellAnchor
|
||||
{
|
||||
auto *anchor = new DrawingTwoCellAnchor(this);
|
||||
anchor->loadFromXml(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,81 @@
|
|||
// xlsxmediafile.cpp
|
||||
|
||||
#include "xlsxmediafile_p.h"
|
||||
|
||||
#include <QCryptographicHash>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
MediaFile::MediaFile(const QByteArray &bytes, const QString &suffix, const QString &mimeType)
|
||||
: m_contents(bytes)
|
||||
, m_suffix(suffix)
|
||||
, m_mimeType(mimeType)
|
||||
, m_index(0)
|
||||
, m_indexValid(false)
|
||||
{
|
||||
m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5);
|
||||
}
|
||||
|
||||
MediaFile::MediaFile(const QString &fileName)
|
||||
: m_fileName(fileName)
|
||||
, m_index(0)
|
||||
, m_indexValid(false)
|
||||
{
|
||||
}
|
||||
|
||||
void MediaFile::set(const QByteArray &bytes, const QString &suffix, const QString &mimeType)
|
||||
{
|
||||
m_contents = bytes;
|
||||
m_suffix = suffix;
|
||||
m_mimeType = mimeType;
|
||||
m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5);
|
||||
m_indexValid = false;
|
||||
}
|
||||
|
||||
void MediaFile::setFileName(const QString &name)
|
||||
{
|
||||
m_fileName = name;
|
||||
}
|
||||
|
||||
QString MediaFile::fileName() const
|
||||
{
|
||||
return m_fileName;
|
||||
}
|
||||
|
||||
QString MediaFile::suffix() const
|
||||
{
|
||||
return m_suffix;
|
||||
}
|
||||
|
||||
QString MediaFile::mimeType() const
|
||||
{
|
||||
return m_mimeType;
|
||||
}
|
||||
|
||||
QByteArray MediaFile::contents() const
|
||||
{
|
||||
return m_contents;
|
||||
}
|
||||
|
||||
int MediaFile::index() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
bool MediaFile::isIndexValid() const
|
||||
{
|
||||
return m_indexValid;
|
||||
}
|
||||
|
||||
void MediaFile::setIndex(int idx)
|
||||
{
|
||||
m_index = idx;
|
||||
m_indexValid = true;
|
||||
}
|
||||
|
||||
QByteArray MediaFile::hashKey() const
|
||||
{
|
||||
return m_hashKey;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,77 @@
|
|||
// xlsxnumformatparser.cpp
|
||||
|
||||
#include "xlsxnumformatparser_p.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
bool NumFormatParser::isDateTime(const QString &formatCode)
|
||||
{
|
||||
for (int i = 0; i < formatCode.length(); ++i) {
|
||||
const QChar &c = formatCode[i];
|
||||
|
||||
switch (c.unicode()) {
|
||||
case '[':
|
||||
// [h], [m], [s] are valid format for time
|
||||
if (i < formatCode.length() - 2 && formatCode[i + 2] == QLatin1Char(']')) {
|
||||
const QChar cc = formatCode[i + 1].toLower();
|
||||
if (cc == QLatin1Char('h') || cc == QLatin1Char('m') || cc == QLatin1Char('s'))
|
||||
return true;
|
||||
i += 2;
|
||||
break;
|
||||
} else {
|
||||
// condition or color: don't care, ignore
|
||||
while (i < formatCode.length() && formatCode[i] != QLatin1Char(']'))
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
|
||||
// quoted plain text block: don't care, ignore
|
||||
case '"':
|
||||
while (i < formatCode.length() - 1) {
|
||||
++i;
|
||||
if (formatCode[i] == QLatin1Char('"')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// escaped char: don't care, ignore
|
||||
case '\\':
|
||||
if (i < formatCode.length() - 1)
|
||||
++i;
|
||||
break;
|
||||
|
||||
// date/time can only be positive number,
|
||||
// so only the first section of the format make sense.
|
||||
case '#': // this is new an working // https://github.com/QtExcel/QXlsx/issues/190
|
||||
case ';':
|
||||
return false;
|
||||
break;
|
||||
|
||||
// days
|
||||
case 'D':
|
||||
case 'd':
|
||||
// years
|
||||
case 'Y':
|
||||
case 'y':
|
||||
// hours
|
||||
case 'H':
|
||||
case 'h':
|
||||
// seconds
|
||||
case 'S':
|
||||
case 's':
|
||||
// minutes or months, depending on context
|
||||
case 'M':
|
||||
case 'm':
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,176 @@
|
|||
// xlsxrelationships.cpp
|
||||
|
||||
#include "xlsxrelationships_p.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
const QLatin1String
|
||||
schema_doc("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||
const QLatin1String schema_msPackage("http://schemas.microsoft.com/office/2006/relationships");
|
||||
const QLatin1String schema_package("http://schemas.openxmlformats.org/package/2006/relationships");
|
||||
// const QString schema_worksheet =
|
||||
// QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||
Relationships::Relationships()
|
||||
{
|
||||
}
|
||||
|
||||
QList<XlsxRelationship> Relationships::documentRelationships(const QString &relativeType) const
|
||||
{
|
||||
return relationships(schema_doc + relativeType);
|
||||
}
|
||||
|
||||
void Relationships::addDocumentRelationship(const QString &relativeType, const QString &target)
|
||||
{
|
||||
addRelationship(schema_doc + relativeType, target);
|
||||
}
|
||||
|
||||
QList<XlsxRelationship> Relationships::msPackageRelationships(const QString &relativeType) const
|
||||
{
|
||||
return relationships(schema_msPackage + relativeType);
|
||||
}
|
||||
|
||||
void Relationships::addMsPackageRelationship(const QString &relativeType, const QString &target)
|
||||
{
|
||||
addRelationship(schema_msPackage + relativeType, target);
|
||||
}
|
||||
|
||||
QList<XlsxRelationship> Relationships::packageRelationships(const QString &relativeType) const
|
||||
{
|
||||
return relationships(schema_package + relativeType);
|
||||
}
|
||||
|
||||
void Relationships::addPackageRelationship(const QString &relativeType, const QString &target)
|
||||
{
|
||||
addRelationship(schema_package + relativeType, target);
|
||||
}
|
||||
|
||||
QList<XlsxRelationship> Relationships::worksheetRelationships(const QString &relativeType) const
|
||||
{
|
||||
return relationships(schema_doc + relativeType);
|
||||
}
|
||||
|
||||
void Relationships::addWorksheetRelationship(const QString &relativeType,
|
||||
const QString &target,
|
||||
const QString &targetMode)
|
||||
{
|
||||
addRelationship(schema_doc + relativeType, target, targetMode);
|
||||
}
|
||||
|
||||
QList<XlsxRelationship> Relationships::relationships(const QString &type) const
|
||||
{
|
||||
QList<XlsxRelationship> res;
|
||||
for (const XlsxRelationship &ship : m_relationships) {
|
||||
if (ship.type == type)
|
||||
res.append(ship);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void Relationships::addRelationship(const QString &type,
|
||||
const QString &target,
|
||||
const QString &targetMode)
|
||||
{
|
||||
XlsxRelationship relation;
|
||||
relation.id = QStringLiteral("rId%1").arg(m_relationships.size() + 1);
|
||||
relation.type = type;
|
||||
relation.target = target;
|
||||
relation.targetMode = targetMode;
|
||||
|
||||
m_relationships.append(relation);
|
||||
}
|
||||
|
||||
void Relationships::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
QXmlStreamWriter writer(device);
|
||||
|
||||
writer.writeStartDocument(QStringLiteral("1.0"), true);
|
||||
writer.writeStartElement(QStringLiteral("Relationships"));
|
||||
writer.writeAttribute(
|
||||
QStringLiteral("xmlns"),
|
||||
QStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships"));
|
||||
for (const XlsxRelationship &relation : m_relationships) {
|
||||
writer.writeStartElement(QStringLiteral("Relationship"));
|
||||
writer.writeAttribute(QStringLiteral("Id"), relation.id);
|
||||
writer.writeAttribute(QStringLiteral("Type"), relation.type);
|
||||
writer.writeAttribute(QStringLiteral("Target"), relation.target);
|
||||
if (!relation.targetMode.isNull())
|
||||
writer.writeAttribute(QStringLiteral("TargetMode"), relation.targetMode);
|
||||
writer.writeEndElement();
|
||||
}
|
||||
writer.writeEndElement(); // Relationships
|
||||
writer.writeEndDocument();
|
||||
}
|
||||
|
||||
QByteArray Relationships::saveToXmlData() const
|
||||
{
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
saveToXmlFile(&buffer);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
bool Relationships::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
clear();
|
||||
QXmlStreamReader reader(device);
|
||||
while (!reader.atEnd()) {
|
||||
QXmlStreamReader::TokenType token = reader.readNext();
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QStringLiteral("Relationship")) {
|
||||
QXmlStreamAttributes attributes = reader.attributes();
|
||||
XlsxRelationship relationship;
|
||||
relationship.id = attributes.value(QLatin1String("Id")).toString();
|
||||
relationship.type = attributes.value(QLatin1String("Type")).toString();
|
||||
relationship.target = attributes.value(QLatin1String("Target")).toString();
|
||||
relationship.targetMode = attributes.value(QLatin1String("TargetMode")).toString();
|
||||
m_relationships.append(relationship);
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.hasError())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Relationships::loadFromXmlData(const QByteArray &data)
|
||||
{
|
||||
QBuffer buffer;
|
||||
buffer.setData(data);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
return loadFromXmlFile(&buffer);
|
||||
}
|
||||
|
||||
XlsxRelationship Relationships::getRelationshipById(const QString &id) const
|
||||
{
|
||||
for (const XlsxRelationship &ship : m_relationships) {
|
||||
if (ship.id == id)
|
||||
return ship;
|
||||
}
|
||||
return XlsxRelationship();
|
||||
}
|
||||
|
||||
void Relationships::clear()
|
||||
{
|
||||
m_relationships.clear();
|
||||
}
|
||||
|
||||
int Relationships::count() const
|
||||
{
|
||||
return m_relationships.count();
|
||||
}
|
||||
|
||||
bool Relationships::isEmpty() const
|
||||
{
|
||||
return m_relationships.isEmpty();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,325 @@
|
|||
// xlsxrichstring.cpp
|
||||
|
||||
#include "xlsxrichstring.h"
|
||||
|
||||
#include "xlsxformat_p.h"
|
||||
#include "xlsxrichstring_p.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTextDocument>
|
||||
#include <QTextFragment>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
RichStringPrivate::RichStringPrivate()
|
||||
: _dirty(true)
|
||||
{
|
||||
}
|
||||
|
||||
RichStringPrivate::RichStringPrivate(const RichStringPrivate &other)
|
||||
: QSharedData(other)
|
||||
, fragmentTexts(other.fragmentTexts)
|
||||
, fragmentFormats(other.fragmentFormats)
|
||||
, _idKey(other.idKey())
|
||||
, _dirty(other._dirty)
|
||||
{
|
||||
}
|
||||
|
||||
RichStringPrivate::~RichStringPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\class RichString
|
||||
\inmodule QtXlsx
|
||||
\brief This class add support for the rich text string of the cell.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a null string.
|
||||
*/
|
||||
RichString::RichString()
|
||||
: d(new RichStringPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a plain string with the given \a text.
|
||||
*/
|
||||
RichString::RichString(const QString &text)
|
||||
: d(new RichStringPrivate)
|
||||
{
|
||||
addFragment(text, Format());
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a copy of \a other.
|
||||
*/
|
||||
RichString::RichString(const RichString &other)
|
||||
: d(other.d)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Destructs the string.
|
||||
*/
|
||||
RichString::~RichString()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Assigns \a other to this string and returns a reference to this string
|
||||
*/
|
||||
RichString &RichString::operator=(const RichString &other)
|
||||
{
|
||||
if (this != &other) // Self-assignment check [cert-oop54-cpp]
|
||||
{
|
||||
this->d = other.d;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the rich string as a QVariant
|
||||
*/
|
||||
RichString::operator QVariant() const
|
||||
{
|
||||
const auto &cref
|
||||
#if QT_VERSION >= 0x060000 // Qt 6.0 or over
|
||||
= QMetaType::fromType<RichString>();
|
||||
#else
|
||||
= qMetaTypeId<RichString>();
|
||||
#endif
|
||||
return QVariant(cref, this);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if this is rich text string.
|
||||
*/
|
||||
bool RichString::isRichString() const
|
||||
{
|
||||
if (fragmentCount() > 1) // Is this enough??
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true is this is an Null string.
|
||||
*/
|
||||
bool RichString::isNull() const
|
||||
{
|
||||
return d->fragmentTexts.isEmpty();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true is this is an empty string.
|
||||
*/
|
||||
bool RichString::isEmtpy() const
|
||||
{
|
||||
return std::all_of(d->fragmentTexts.begin(), d->fragmentTexts.end(),
|
||||
[](const QString &str) { return str.isEmpty(); });
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts to plain text string.
|
||||
*/
|
||||
QString RichString::toPlainString() const
|
||||
{
|
||||
if (isEmtpy())
|
||||
return QString();
|
||||
if (d->fragmentTexts.size() == 1)
|
||||
return d->fragmentTexts[0];
|
||||
|
||||
return d->fragmentTexts.join(QString());
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts to html string
|
||||
*/
|
||||
QString RichString::toHtml() const
|
||||
{
|
||||
//: Todo
|
||||
return QString();
|
||||
}
|
||||
|
||||
/*!
|
||||
Replaces the entire contents of the document
|
||||
with the given HTML-formatted text in the \a text string
|
||||
*/
|
||||
void RichString::setHtml(const QString &text)
|
||||
{
|
||||
QTextDocument doc;
|
||||
doc.setHtml(text);
|
||||
QTextBlock block = doc.firstBlock();
|
||||
QTextBlock::iterator it;
|
||||
for (it = block.begin(); !(it.atEnd()); ++it) {
|
||||
QTextFragment textFragment = it.fragment();
|
||||
if (textFragment.isValid()) {
|
||||
Format fmt;
|
||||
fmt.setFont(textFragment.charFormat().font());
|
||||
fmt.setFontColor(textFragment.charFormat().foreground().color());
|
||||
addFragment(textFragment.text(), fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns fragment count.
|
||||
*/
|
||||
int RichString::fragmentCount() const
|
||||
{
|
||||
return d->fragmentTexts.size();
|
||||
}
|
||||
|
||||
/*!
|
||||
Appends a fragment with the given \a text and \a format.
|
||||
*/
|
||||
void RichString::addFragment(const QString &text, const Format &format)
|
||||
{
|
||||
d->fragmentTexts.append(text);
|
||||
d->fragmentFormats.append(format);
|
||||
d->_dirty = true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns fragment text at the position \a index.
|
||||
*/
|
||||
QString RichString::fragmentText(int index) const
|
||||
{
|
||||
if (index < 0 || index >= fragmentCount())
|
||||
return QString();
|
||||
|
||||
return d->fragmentTexts[index];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns fragment format at the position \a index.
|
||||
*/
|
||||
Format RichString::fragmentFormat(int index) const
|
||||
{
|
||||
if (index < 0 || index >= fragmentCount())
|
||||
return Format();
|
||||
|
||||
return d->fragmentFormats[index];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
QByteArray RichStringPrivate::idKey() const
|
||||
{
|
||||
if (_dirty) {
|
||||
auto rs = const_cast<RichStringPrivate *>(this);
|
||||
QByteArray bytes;
|
||||
if (fragmentTexts.size() == 1) {
|
||||
bytes = fragmentTexts[0].toUtf8();
|
||||
} else {
|
||||
// Generate a hash value base on QByteArray ?
|
||||
bytes.append("@@QtXlsxRichString=");
|
||||
for (int i = 0; i < fragmentTexts.size(); ++i) {
|
||||
bytes.append("@Text");
|
||||
bytes.append(fragmentTexts[i].toUtf8());
|
||||
bytes.append("@Format");
|
||||
if (fragmentFormats[i].hasFontData())
|
||||
bytes.append(fragmentFormats[i].fontKey());
|
||||
}
|
||||
}
|
||||
rs->_idKey = bytes;
|
||||
rs->_dirty = false;
|
||||
}
|
||||
|
||||
return _idKey;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if this string \a rs1 is equal to string \a rs2;
|
||||
otherwise returns false.
|
||||
*/
|
||||
bool operator==(const RichString &rs1, const RichString &rs2)
|
||||
{
|
||||
if (rs1.fragmentCount() != rs2.fragmentCount())
|
||||
return false;
|
||||
|
||||
return rs1.d->idKey() == rs2.d->idKey();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if this string \a rs1 is not equal to string \a rs2;
|
||||
otherwise returns false.
|
||||
*/
|
||||
bool operator!=(const RichString &rs1, const RichString &rs2)
|
||||
{
|
||||
if (rs1.fragmentCount() != rs2.fragmentCount())
|
||||
return true;
|
||||
|
||||
return rs1.d->idKey() != rs2.d->idKey();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
bool operator<(const RichString &rs1, const RichString &rs2)
|
||||
{
|
||||
return rs1.d->idKey() < rs2.d->idKey();
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Returns true if this string \a rs1 is equal to string \a rs2;
|
||||
otherwise returns false.
|
||||
*/
|
||||
bool operator==(const RichString &rs1, const QString &rs2)
|
||||
{
|
||||
if (rs1.fragmentCount() == 1 && rs1.fragmentText(0) == rs2) // format == 0
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Returns true if this string \a rs1 is not equal to string \a rs2;
|
||||
otherwise returns false.
|
||||
*/
|
||||
bool operator!=(const RichString &rs1, const QString &rs2)
|
||||
{
|
||||
if (rs1.fragmentCount() == 1 && rs1.fragmentText(0) == rs2) // format == 0
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Returns true if this string \a rs1 is equal to string \a rs2;
|
||||
otherwise returns false.
|
||||
*/
|
||||
bool operator==(const QString &rs1, const RichString &rs2)
|
||||
{
|
||||
return rs2 == rs1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Returns true if this string \a rs1 is not equal to string \a rs2;
|
||||
otherwise returns false.
|
||||
*/
|
||||
bool operator!=(const QString &rs1, const RichString &rs2)
|
||||
{
|
||||
return rs2 != rs1;
|
||||
}
|
||||
|
||||
uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW
|
||||
{
|
||||
return qHash(rs.d->idKey(), seed);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
QDebug operator<<(QDebug dbg, const RichString &rs)
|
||||
{
|
||||
dbg.nospace() << "QXlsx::RichString(" << rs.d->fragmentTexts << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,394 @@
|
|||
// xlsxsharedstrings.cpp
|
||||
|
||||
#include "xlsxcolor_p.h"
|
||||
#include "xlsxformat_p.h"
|
||||
#include "xlsxrichstring.h"
|
||||
#include "xlsxsharedstrings_p.h"
|
||||
#include "xlsxutility_p.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
/*
|
||||
* Note that, when we open an existing .xlsx file (broken file?),
|
||||
* duplicated string items may exist in the shared string table.
|
||||
*
|
||||
* In such case, the size of stringList will larger than stringTable.
|
||||
* Duplicated items can be removed once we loaded all the worksheets.
|
||||
*/
|
||||
|
||||
SharedStrings::SharedStrings(CreateFlag flag)
|
||||
: AbstractOOXmlFile(flag)
|
||||
{
|
||||
m_stringCount = 0;
|
||||
}
|
||||
|
||||
int SharedStrings::count() const
|
||||
{
|
||||
return m_stringCount;
|
||||
}
|
||||
|
||||
bool SharedStrings::isEmpty() const
|
||||
{
|
||||
return m_stringList.isEmpty();
|
||||
}
|
||||
|
||||
int SharedStrings::addSharedString(const QString &string)
|
||||
{
|
||||
return addSharedString(RichString(string));
|
||||
}
|
||||
|
||||
int SharedStrings::addSharedString(const RichString &string)
|
||||
{
|
||||
m_stringCount += 1;
|
||||
|
||||
auto it = m_stringTable.find(string);
|
||||
if (it != m_stringTable.end()) {
|
||||
it->count += 1;
|
||||
return it->index;
|
||||
}
|
||||
|
||||
int index = m_stringList.size();
|
||||
m_stringTable[string] = XlsxSharedStringInfo(index);
|
||||
m_stringList.append(string);
|
||||
return index;
|
||||
}
|
||||
|
||||
void SharedStrings::incRefByStringIndex(int idx)
|
||||
{
|
||||
if (idx < 0 || idx >= m_stringList.size()) {
|
||||
qDebug("SharedStrings: invalid index");
|
||||
return;
|
||||
}
|
||||
|
||||
addSharedString(m_stringList[idx]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Broken, don't use.
|
||||
*/
|
||||
void SharedStrings::removeSharedString(const QString &string)
|
||||
{
|
||||
removeSharedString(RichString(string));
|
||||
}
|
||||
|
||||
/*
|
||||
* Broken, don't use.
|
||||
*/
|
||||
void SharedStrings::removeSharedString(const RichString &string)
|
||||
{
|
||||
auto it = m_stringTable.find(string);
|
||||
if (it == m_stringTable.end())
|
||||
return;
|
||||
|
||||
m_stringCount -= 1;
|
||||
|
||||
it->count -= 1;
|
||||
|
||||
if (it->count <= 0) {
|
||||
for (int i = it->index + 1; i < m_stringList.size(); ++i)
|
||||
m_stringTable[m_stringList[i]].index -= 1;
|
||||
|
||||
m_stringList.removeAt(it->index);
|
||||
m_stringTable.remove(string);
|
||||
}
|
||||
}
|
||||
|
||||
int SharedStrings::getSharedStringIndex(const QString &string) const
|
||||
{
|
||||
return getSharedStringIndex(RichString(string));
|
||||
}
|
||||
|
||||
int SharedStrings::getSharedStringIndex(const RichString &string) const
|
||||
{
|
||||
auto it = m_stringTable.constFind(string);
|
||||
if (it != m_stringTable.constEnd())
|
||||
return it->index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
RichString SharedStrings::getSharedString(int index) const
|
||||
{
|
||||
if (index < m_stringList.count() && index >= 0)
|
||||
return m_stringList[index];
|
||||
return RichString();
|
||||
}
|
||||
|
||||
QList<RichString> SharedStrings::getSharedStrings() const
|
||||
{
|
||||
return m_stringList;
|
||||
}
|
||||
|
||||
void SharedStrings::writeRichStringPart_rPr(QXmlStreamWriter &writer, const Format &format) const
|
||||
{
|
||||
if (!format.hasFontData())
|
||||
return;
|
||||
|
||||
if (format.fontBold())
|
||||
writer.writeEmptyElement(QStringLiteral("b"));
|
||||
if (format.fontItalic())
|
||||
writer.writeEmptyElement(QStringLiteral("i"));
|
||||
if (format.fontStrikeOut())
|
||||
writer.writeEmptyElement(QStringLiteral("strike"));
|
||||
if (format.fontOutline())
|
||||
writer.writeEmptyElement(QStringLiteral("outline"));
|
||||
if (format.boolProperty(FormatPrivate::P_Font_Shadow))
|
||||
writer.writeEmptyElement(QStringLiteral("shadow"));
|
||||
if (format.hasProperty(FormatPrivate::P_Font_Underline)) {
|
||||
Format::FontUnderline u = format.fontUnderline();
|
||||
if (u != Format::FontUnderlineNone) {
|
||||
writer.writeEmptyElement(QStringLiteral("u"));
|
||||
if (u == Format::FontUnderlineDouble)
|
||||
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("double"));
|
||||
else if (u == Format::FontUnderlineSingleAccounting)
|
||||
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("singleAccounting"));
|
||||
else if (u == Format::FontUnderlineDoubleAccounting)
|
||||
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("doubleAccounting"));
|
||||
}
|
||||
}
|
||||
if (format.hasProperty(FormatPrivate::P_Font_Script)) {
|
||||
Format::FontScript s = format.fontScript();
|
||||
if (s != Format::FontScriptNormal) {
|
||||
writer.writeEmptyElement(QStringLiteral("vertAlign"));
|
||||
if (s == Format::FontScriptSuper)
|
||||
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("superscript"));
|
||||
else
|
||||
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("subscript"));
|
||||
}
|
||||
}
|
||||
|
||||
if (format.hasProperty(FormatPrivate::P_Font_Size)) {
|
||||
writer.writeEmptyElement(QStringLiteral("sz"));
|
||||
writer.writeAttribute(QStringLiteral("val"), QString::number(format.fontSize()));
|
||||
}
|
||||
|
||||
if (format.hasProperty(FormatPrivate::P_Font_Color)) {
|
||||
auto color = format.property(FormatPrivate::P_Font_Color).value<XlsxColor>();
|
||||
color.saveToXml(writer);
|
||||
}
|
||||
|
||||
if (!format.fontName().isEmpty()) {
|
||||
writer.writeEmptyElement(QStringLiteral("rFont"));
|
||||
writer.writeAttribute(QStringLiteral("val"), format.fontName());
|
||||
}
|
||||
if (format.hasProperty(FormatPrivate::P_Font_Family)) {
|
||||
writer.writeEmptyElement(QStringLiteral("family"));
|
||||
writer.writeAttribute(QStringLiteral("val"),
|
||||
QString::number(format.intProperty(FormatPrivate::P_Font_Family)));
|
||||
}
|
||||
|
||||
if (format.hasProperty(FormatPrivate::P_Font_Scheme)) {
|
||||
writer.writeEmptyElement(QStringLiteral("scheme"));
|
||||
writer.writeAttribute(QStringLiteral("val"),
|
||||
format.stringProperty(FormatPrivate::P_Font_Scheme));
|
||||
}
|
||||
}
|
||||
|
||||
void SharedStrings::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
QXmlStreamWriter writer(device);
|
||||
|
||||
if (m_stringList.size() != m_stringTable.size()) {
|
||||
// Duplicated string items exist in m_stringList
|
||||
// Clean up can not be done here, as the indices
|
||||
// have been used when we save the worksheets part.
|
||||
}
|
||||
|
||||
writer.writeStartDocument(QStringLiteral("1.0"), true);
|
||||
writer.writeStartElement(QStringLiteral("sst"));
|
||||
writer.writeAttribute(
|
||||
QStringLiteral("xmlns"),
|
||||
QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main"));
|
||||
writer.writeAttribute(QStringLiteral("count"), QString::number(m_stringCount));
|
||||
writer.writeAttribute(QStringLiteral("uniqueCount"), QString::number(m_stringList.size()));
|
||||
|
||||
for (const RichString &string : m_stringList) {
|
||||
writer.writeStartElement(QStringLiteral("si"));
|
||||
if (string.isRichString()) {
|
||||
// Rich text string
|
||||
for (int i = 0; i < string.fragmentCount(); ++i) {
|
||||
writer.writeStartElement(QStringLiteral("r"));
|
||||
if (string.fragmentFormat(i).hasFontData()) {
|
||||
writer.writeStartElement(QStringLiteral("rPr"));
|
||||
writeRichStringPart_rPr(writer, string.fragmentFormat(i));
|
||||
writer.writeEndElement(); // rPr
|
||||
}
|
||||
writer.writeStartElement(QStringLiteral("t"));
|
||||
if (isSpaceReserveNeeded(string.fragmentText(i)))
|
||||
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
|
||||
writer.writeCharacters(string.fragmentText(i));
|
||||
writer.writeEndElement(); // t
|
||||
|
||||
writer.writeEndElement(); // r
|
||||
}
|
||||
} else {
|
||||
writer.writeStartElement(QStringLiteral("t"));
|
||||
QString pString = string.toPlainString();
|
||||
if (isSpaceReserveNeeded(pString))
|
||||
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
|
||||
writer.writeCharacters(pString);
|
||||
writer.writeEndElement(); // t
|
||||
}
|
||||
writer.writeEndElement(); // si
|
||||
}
|
||||
|
||||
writer.writeEndElement(); // sst
|
||||
writer.writeEndDocument();
|
||||
}
|
||||
|
||||
void SharedStrings::readString(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("si"));
|
||||
|
||||
RichString richString;
|
||||
|
||||
while (!reader.atEnd() && !(reader.name() == QLatin1String("si") &&
|
||||
reader.tokenType() == QXmlStreamReader::EndElement)) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("r"))
|
||||
readRichStringPart(reader, richString);
|
||||
else if (reader.name() == QLatin1String("t"))
|
||||
readPlainStringPart(reader, richString);
|
||||
}
|
||||
}
|
||||
|
||||
int idx = m_stringList.size();
|
||||
m_stringTable[richString] = XlsxSharedStringInfo(idx, 0);
|
||||
m_stringList.append(richString);
|
||||
}
|
||||
|
||||
void SharedStrings::readRichStringPart(QXmlStreamReader &reader, RichString &richString)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("r"));
|
||||
|
||||
QString text;
|
||||
Format format;
|
||||
while (!reader.atEnd() && !(reader.name() == QLatin1String("r") &&
|
||||
reader.tokenType() == QXmlStreamReader::EndElement)) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("rPr")) {
|
||||
format = readRichStringPart_rPr(reader);
|
||||
} else if (reader.name() == QLatin1String("t")) {
|
||||
text = reader.readElementText();
|
||||
}
|
||||
}
|
||||
}
|
||||
richString.addFragment(text, format);
|
||||
}
|
||||
|
||||
void SharedStrings::readPlainStringPart(QXmlStreamReader &reader, RichString &richString)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("t"));
|
||||
|
||||
// QXmlStreamAttributes attributes = reader.attributes();
|
||||
|
||||
// NOTICE: CHECK POINT
|
||||
QString text = reader.readElementText();
|
||||
richString.addFragment(text, Format());
|
||||
}
|
||||
|
||||
Format SharedStrings::readRichStringPart_rPr(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("rPr"));
|
||||
Format format;
|
||||
while (!reader.atEnd() && !(reader.name() == QLatin1String("rPr") &&
|
||||
reader.tokenType() == QXmlStreamReader::EndElement)) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
QXmlStreamAttributes attributes = reader.attributes();
|
||||
if (reader.name() == QLatin1String("rFont")) {
|
||||
format.setFontName(attributes.value(QLatin1String("val")).toString());
|
||||
} else if (reader.name() == QLatin1String("charset")) {
|
||||
format.setProperty(FormatPrivate::P_Font_Charset,
|
||||
attributes.value(QLatin1String("val")).toInt());
|
||||
} else if (reader.name() == QLatin1String("family")) {
|
||||
format.setProperty(FormatPrivate::P_Font_Family,
|
||||
attributes.value(QLatin1String("val")).toInt());
|
||||
} else if (reader.name() == QLatin1String("b")) {
|
||||
format.setFontBold(true);
|
||||
} else if (reader.name() == QLatin1String("i")) {
|
||||
format.setFontItalic(true);
|
||||
} else if (reader.name() == QLatin1String("strike")) {
|
||||
format.setFontStrikeOut(true);
|
||||
} else if (reader.name() == QLatin1String("outline")) {
|
||||
format.setFontOutline(true);
|
||||
} else if (reader.name() == QLatin1String("shadow")) {
|
||||
format.setProperty(FormatPrivate::P_Font_Shadow, true);
|
||||
} else if (reader.name() == QLatin1String("condense")) {
|
||||
format.setProperty(FormatPrivate::P_Font_Condense,
|
||||
attributes.value(QLatin1String("val")).toInt());
|
||||
} else if (reader.name() == QLatin1String("extend")) {
|
||||
format.setProperty(FormatPrivate::P_Font_Extend,
|
||||
attributes.value(QLatin1String("val")).toInt());
|
||||
} else if (reader.name() == QLatin1String("color")) {
|
||||
XlsxColor color;
|
||||
color.loadFromXml(reader);
|
||||
format.setProperty(FormatPrivate::P_Font_Color, color);
|
||||
} else if (reader.name() == QLatin1String("sz")) {
|
||||
format.setFontSize(attributes.value(QLatin1String("val")).toInt());
|
||||
} else if (reader.name() == QLatin1String("u")) {
|
||||
QString value = attributes.value(QLatin1String("val")).toString();
|
||||
if (value == QLatin1String("double"))
|
||||
format.setFontUnderline(Format::FontUnderlineDouble);
|
||||
else if (value == QLatin1String("doubleAccounting"))
|
||||
format.setFontUnderline(Format::FontUnderlineDoubleAccounting);
|
||||
else if (value == QLatin1String("singleAccounting"))
|
||||
format.setFontUnderline(Format::FontUnderlineSingleAccounting);
|
||||
else
|
||||
format.setFontUnderline(Format::FontUnderlineSingle);
|
||||
} else if (reader.name() == QLatin1String("vertAlign")) {
|
||||
QString value = attributes.value(QLatin1String("val")).toString();
|
||||
if (value == QLatin1String("superscript"))
|
||||
format.setFontScript(Format::FontScriptSuper);
|
||||
else if (value == QLatin1String("subscript"))
|
||||
format.setFontScript(Format::FontScriptSub);
|
||||
} else if (reader.name() == QLatin1String("scheme")) {
|
||||
format.setProperty(FormatPrivate::P_Font_Scheme,
|
||||
attributes.value(QLatin1String("val")).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
bool SharedStrings::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
QXmlStreamReader reader(device);
|
||||
int count = 0;
|
||||
bool hasUniqueCountAttr = true;
|
||||
while (!reader.atEnd()) {
|
||||
QXmlStreamReader::TokenType token = reader.readNext();
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("sst")) {
|
||||
QXmlStreamAttributes attributes = reader.attributes();
|
||||
hasUniqueCountAttr = attributes.hasAttribute(QLatin1String("uniqueCount"));
|
||||
if (hasUniqueCountAttr)
|
||||
count = attributes.value(QLatin1String("uniqueCount")).toInt();
|
||||
} else if (reader.name() == QLatin1String("si")) {
|
||||
readString(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUniqueCountAttr && m_stringList.size() != count) {
|
||||
qDebug("Error: Shared string count");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_stringList.size() != m_stringTable.size()) {
|
||||
// qDebug("Warning: Duplicated items exist in shared string table.");
|
||||
// Nothing we can do here, as indices of the strings will be used when loading sheets.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,36 @@
|
|||
// xlsxsimpleooxmlfile.cpp
|
||||
|
||||
#include "xlsxsimpleooxmlfile_p.h"
|
||||
|
||||
#include <QIODevice>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
SimpleOOXmlFile::SimpleOOXmlFile(CreateFlag flag)
|
||||
: AbstractOOXmlFile(flag)
|
||||
{
|
||||
}
|
||||
|
||||
void SimpleOOXmlFile::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
device->write(xmlData);
|
||||
}
|
||||
|
||||
QByteArray SimpleOOXmlFile::saveToXmlData() const
|
||||
{
|
||||
return xmlData;
|
||||
}
|
||||
|
||||
bool SimpleOOXmlFile::loadFromXmlData(const QByteArray &data)
|
||||
{
|
||||
xmlData = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleOOXmlFile::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
xmlData = device->readAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,233 @@
|
|||
// xlsxtheme.cpp
|
||||
|
||||
#include "xlsxtheme_p.h"
|
||||
|
||||
#include <QIODevice>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
const char *defaultXmlData =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
|
||||
"<a:theme xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" name=\"Office "
|
||||
"\xe4\xb8\xbb\xe9\xa2\x98\">"
|
||||
"<a:themeElements>"
|
||||
"<a:clrScheme name=\"Office\">"
|
||||
"<a:dk1><a:sysClr val=\"windowText\" lastClr=\"000000\"/></a:dk1>"
|
||||
"<a:lt1><a:sysClr val=\"window\" lastClr=\"FFFFFF\"/></a:lt1>"
|
||||
"<a:dk2><a:srgbClr val=\"1F497D\"/></a:dk2>"
|
||||
"<a:lt2><a:srgbClr val=\"EEECE1\"/></a:lt2>"
|
||||
"<a:accent1><a:srgbClr val=\"4F81BD\"/></a:accent1>"
|
||||
"<a:accent2><a:srgbClr val=\"C0504D\"/></a:accent2>"
|
||||
"<a:accent3><a:srgbClr val=\"9BBB59\"/></a:accent3>"
|
||||
"<a:accent4><a:srgbClr val=\"8064A2\"/></a:accent4>"
|
||||
"<a:accent5><a:srgbClr val=\"4BACC6\"/></a:accent5>"
|
||||
"<a:accent6><a:srgbClr val=\"F79646\"/></a:accent6>"
|
||||
"<a:hlink><a:srgbClr val=\"0000FF\"/></a:hlink>"
|
||||
"<a:folHlink><a:srgbClr val=\"800080\"/></a:folHlink>"
|
||||
"</a:clrScheme>"
|
||||
"<a:fontScheme name=\"Office\">"
|
||||
"<a:majorFont>"
|
||||
"<a:latin typeface=\"Cambria\"/>"
|
||||
"<a:ea typeface=\"\"/>"
|
||||
"<a:cs typeface=\"\"/>"
|
||||
"<a:font script=\"Jpan\" typeface=\"\xef\xbc\xad\xef\xbc\xb3 "
|
||||
"\xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf\"/>"
|
||||
"<a:font script=\"Hang\" typeface=\"\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95\"/>"
|
||||
"<a:font script=\"Hans\" typeface=\"\xe5\xae\x8b\xe4\xbd\x93\"/>"
|
||||
"<a:font script=\"Hant\" typeface=\"\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94\"/>"
|
||||
"<a:font script=\"Arab\" typeface=\"Times New Roman\"/>"
|
||||
"<a:font script=\"Hebr\" typeface=\"Times New Roman\"/>"
|
||||
"<a:font script=\"Thai\" typeface=\"Tahoma\"/>"
|
||||
"<a:font script=\"Ethi\" typeface=\"Nyala\"/>"
|
||||
"<a:font script=\"Beng\" typeface=\"Vrinda\"/>"
|
||||
"<a:font script=\"Gujr\" typeface=\"Shruti\"/>"
|
||||
"<a:font script=\"Khmr\" typeface=\"MoolBoran\"/>"
|
||||
"<a:font script=\"Knda\" typeface=\"Tunga\"/>"
|
||||
"<a:font script=\"Guru\" typeface=\"Raavi\"/>"
|
||||
"<a:font script=\"Cans\" typeface=\"Euphemia\"/>"
|
||||
"<a:font script=\"Cher\" typeface=\"Plantagenet Cherokee\"/>"
|
||||
"<a:font script=\"Yiii\" typeface=\"Microsoft Yi Baiti\"/>"
|
||||
"<a:font script=\"Tibt\" typeface=\"Microsoft Himalaya\"/>"
|
||||
"<a:font script=\"Thaa\" typeface=\"MV Boli\"/>"
|
||||
"<a:font script=\"Deva\" typeface=\"Mangal\"/>"
|
||||
"<a:font script=\"Telu\" typeface=\"Gautami\"/>"
|
||||
"<a:font script=\"Taml\" typeface=\"Latha\"/>"
|
||||
"<a:font script=\"Syrc\" typeface=\"Estrangelo Edessa\"/>"
|
||||
"<a:font script=\"Orya\" typeface=\"Kalinga\"/>"
|
||||
"<a:font script=\"Mlym\" typeface=\"Kartika\"/>"
|
||||
"<a:font script=\"Laoo\" typeface=\"DokChampa\"/>"
|
||||
"<a:font script=\"Sinh\" typeface=\"Iskoola Pota\"/>"
|
||||
"<a:font script=\"Mong\" typeface=\"Mongolian Baiti\"/>"
|
||||
"<a:font script=\"Viet\" typeface=\"Times New Roman\"/>"
|
||||
"<a:font script=\"Uigh\" typeface=\"Microsoft Uighur\"/>"
|
||||
"</a:majorFont>"
|
||||
"<a:minorFont>"
|
||||
"<a:latin typeface=\"Calibri\"/>"
|
||||
"<a:ea typeface=\"\"/>"
|
||||
"<a:cs typeface=\"\"/>"
|
||||
"<a:font script=\"Jpan\" typeface=\"\xef\xbc\xad\xef\xbc\xb3 "
|
||||
"\xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf\"/>"
|
||||
"<a:font script=\"Hang\" typeface=\"\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95\"/>"
|
||||
"<a:font script=\"Hans\" typeface=\"\xe5\xae\x8b\xe4\xbd\x93\"/>"
|
||||
"<a:font script=\"Hant\" typeface=\"\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94\"/>"
|
||||
"<a:font script=\"Arab\" typeface=\"Arial\"/>"
|
||||
"<a:font script=\"Hebr\" typeface=\"Arial\"/>"
|
||||
"<a:font script=\"Thai\" typeface=\"Tahoma\"/>"
|
||||
"<a:font script=\"Ethi\" typeface=\"Nyala\"/>"
|
||||
"<a:font script=\"Beng\" typeface=\"Vrinda\"/>"
|
||||
"<a:font script=\"Gujr\" typeface=\"Shruti\"/>"
|
||||
"<a:font script=\"Khmr\" typeface=\"DaunPenh\"/>"
|
||||
"<a:font script=\"Knda\" typeface=\"Tunga\"/>"
|
||||
"<a:font script=\"Guru\" typeface=\"Raavi\"/>"
|
||||
"<a:font script=\"Cans\" typeface=\"Euphemia\"/>"
|
||||
"<a:font script=\"Cher\" typeface=\"Plantagenet Cherokee\"/>"
|
||||
"<a:font script=\"Yiii\" typeface=\"Microsoft Yi Baiti\"/>"
|
||||
"<a:font script=\"Tibt\" typeface=\"Microsoft Himalaya\"/>"
|
||||
"<a:font script=\"Thaa\" typeface=\"MV Boli\"/>"
|
||||
"<a:font script=\"Deva\" typeface=\"Mangal\"/>"
|
||||
"<a:font script=\"Telu\" typeface=\"Gautami\"/>"
|
||||
"<a:font script=\"Taml\" typeface=\"Latha\"/>"
|
||||
"<a:font script=\"Syrc\" typeface=\"Estrangelo Edessa\"/>"
|
||||
"<a:font script=\"Orya\" typeface=\"Kalinga\"/>"
|
||||
"<a:font script=\"Mlym\" typeface=\"Kartika\"/>"
|
||||
"<a:font script=\"Laoo\" typeface=\"DokChampa\"/>"
|
||||
"<a:font script=\"Sinh\" typeface=\"Iskoola Pota\"/>"
|
||||
"<a:font script=\"Mong\" typeface=\"Mongolian Baiti\"/>"
|
||||
"<a:font script=\"Viet\" typeface=\"Arial\"/>"
|
||||
"<a:font script=\"Uigh\" typeface=\"Microsoft Uighur\"/>"
|
||||
"</a:minorFont>"
|
||||
"</a:fontScheme>"
|
||||
"<a:fmtScheme name=\"Office\">"
|
||||
"<a:fillStyleLst>"
|
||||
"<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>"
|
||||
"<a:gradFill rotWithShape=\"1\">"
|
||||
"<a:gsLst>"
|
||||
"<a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:tint val=\"50000\"/><a:satMod "
|
||||
"val=\"300000\"/></a:schemeClr></a:gs>"
|
||||
"<a:gs pos=\"35000\"><a:schemeClr val=\"phClr\"><a:tint val=\"37000\"/><a:satMod "
|
||||
"val=\"300000\"/></a:schemeClr></a:gs>"
|
||||
"<a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:tint val=\"15000\"/><a:satMod "
|
||||
"val=\"350000\"/></a:schemeClr></a:gs>"
|
||||
"</a:gsLst>"
|
||||
"<a:lin ang=\"16200000\" scaled=\"1\"/>"
|
||||
"</a:gradFill>"
|
||||
"<a:gradFill rotWithShape=\"1\">"
|
||||
"<a:gsLst>"
|
||||
"<a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:shade val=\"51000\"/><a:satMod "
|
||||
"val=\"130000\"/></a:schemeClr></a:gs>"
|
||||
"<a:gs pos=\"80000\"><a:schemeClr val=\"phClr\"><a:shade val=\"93000\"/><a:satMod "
|
||||
"val=\"130000\"/></a:schemeClr></a:gs>"
|
||||
"<a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:shade val=\"94000\"/><a:satMod "
|
||||
"val=\"135000\"/></a:schemeClr></a:gs>"
|
||||
"</a:gsLst>"
|
||||
"<a:lin ang=\"16200000\" scaled=\"0\"/>"
|
||||
"</a:gradFill>"
|
||||
"</a:fillStyleLst>"
|
||||
"<a:lnStyleLst>"
|
||||
"<a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">"
|
||||
"<a:solidFill><a:schemeClr val=\"phClr\"><a:shade val=\"95000\"/><a:satMod "
|
||||
"val=\"105000\"/></a:schemeClr></a:solidFill>"
|
||||
"<a:prstDash val=\"solid\"/>"
|
||||
"</a:ln>"
|
||||
"<a:ln w=\"25400\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">"
|
||||
"<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>"
|
||||
"<a:prstDash val=\"solid\"/>"
|
||||
"</a:ln>"
|
||||
"<a:ln w=\"38100\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">"
|
||||
"<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>"
|
||||
"<a:prstDash val=\"solid\"/>"
|
||||
"</a:ln>"
|
||||
"</a:lnStyleLst>"
|
||||
"<a:effectStyleLst>"
|
||||
"<a:effectStyle>"
|
||||
"<a:effectLst>"
|
||||
"<a:outerShdw blurRad=\"40000\" dist=\"20000\" dir=\"5400000\" rotWithShape=\"0\">"
|
||||
"<a:srgbClr val=\"000000\"><a:alpha val=\"38000\"/></a:srgbClr>"
|
||||
"</a:outerShdw>"
|
||||
"</a:effectLst>"
|
||||
"</a:effectStyle>"
|
||||
"<a:effectStyle>"
|
||||
"<a:effectLst>"
|
||||
"<a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">"
|
||||
"<a:srgbClr val=\"000000\"><a:alpha val=\"35000\"/></a:srgbClr>"
|
||||
"</a:outerShdw>"
|
||||
"</a:effectLst>"
|
||||
"</a:effectStyle>"
|
||||
"<a:effectStyle>"
|
||||
"<a:effectLst>"
|
||||
"<a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">"
|
||||
"<a:srgbClr val=\"000000\"><a:alpha val=\"35000\"/></a:srgbClr>"
|
||||
"</a:outerShdw>"
|
||||
"</a:effectLst>"
|
||||
"<a:scene3d>"
|
||||
"<a:camera prst=\"orthographicFront\"><a:rot lat=\"0\" lon=\"0\" rev=\"0\"/></a:camera>"
|
||||
"<a:lightRig rig=\"threePt\" dir=\"t\"><a:rot lat=\"0\" lon=\"0\" "
|
||||
"rev=\"1200000\"/></a:lightRig>"
|
||||
"</a:scene3d>"
|
||||
"<a:sp3d><a:bevelT w=\"63500\" h=\"25400\"/></a:sp3d>"
|
||||
"</a:effectStyle>"
|
||||
"</a:effectStyleLst>"
|
||||
"<a:bgFillStyleLst>"
|
||||
"<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>"
|
||||
"<a:gradFill rotWithShape=\"1\">"
|
||||
"<a:gsLst>"
|
||||
"<a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:tint val=\"40000\"/><a:satMod "
|
||||
"val=\"350000\"/></a:schemeClr></a:gs>"
|
||||
"<a:gs pos=\"40000\"><a:schemeClr val=\"phClr\"><a:tint val=\"45000\"/><a:shade "
|
||||
"val=\"99000\"/><a:satMod val=\"350000\"/></a:schemeClr></a:gs>"
|
||||
"<a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:shade val=\"20000\"/><a:satMod "
|
||||
"val=\"255000\"/></a:schemeClr></a:gs></a:gsLst>"
|
||||
"<a:path path=\"circle\"><a:fillToRect l=\"50000\" t=\"-80000\" r=\"50000\" "
|
||||
"b=\"180000\"/></a:path>"
|
||||
"</a:gradFill>"
|
||||
"<a:gradFill rotWithShape=\"1\">"
|
||||
"<a:gsLst>"
|
||||
"<a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:tint val=\"80000\"/><a:satMod "
|
||||
"val=\"300000\"/></a:schemeClr></a:gs>"
|
||||
"<a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:shade val=\"30000\"/><a:satMod "
|
||||
"val=\"200000\"/></a:schemeClr></a:gs>"
|
||||
"</a:gsLst>"
|
||||
"<a:path path=\"circle\"><a:fillToRect l=\"50000\" t=\"50000\" r=\"50000\" "
|
||||
"b=\"50000\"/></a:path>"
|
||||
"</a:gradFill>"
|
||||
"</a:bgFillStyleLst>"
|
||||
"</a:fmtScheme>"
|
||||
"</a:themeElements>"
|
||||
"<a:objectDefaults/>"
|
||||
"<a:extraClrSchemeLst/>"
|
||||
"</a:theme>";
|
||||
|
||||
Theme::Theme(CreateFlag flag)
|
||||
: AbstractOOXmlFile(flag)
|
||||
{
|
||||
}
|
||||
|
||||
void Theme::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
if (xmlData.isEmpty())
|
||||
device->write(defaultXmlData);
|
||||
else
|
||||
device->write(xmlData);
|
||||
}
|
||||
|
||||
QByteArray Theme::saveToXmlData() const
|
||||
{
|
||||
if (xmlData.isEmpty())
|
||||
return defaultXmlData;
|
||||
else
|
||||
return xmlData;
|
||||
}
|
||||
|
||||
bool Theme::loadFromXmlData(const QByteArray &data)
|
||||
{
|
||||
xmlData = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Theme::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
xmlData = device->readAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,305 @@
|
|||
// xlsxutility.cpp
|
||||
|
||||
#include "xlsxcellreference.h"
|
||||
#include "xlsxutility_p.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
#include <QColor>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QMap>
|
||||
#include <QPoint>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
bool parseXsdBoolean(const QString &value, bool defaultValue)
|
||||
{
|
||||
if (value == QLatin1String("1") || value == QLatin1String("true"))
|
||||
return true;
|
||||
if (value == QLatin1String("0") || value == QLatin1String("false"))
|
||||
return false;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
QStringList splitPath(const QString &path)
|
||||
{
|
||||
int idx = path.lastIndexOf(QLatin1Char('/'));
|
||||
if (idx == -1)
|
||||
return {QStringLiteral("."), path};
|
||||
|
||||
return {path.left(idx), path.mid(idx + 1)};
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the .rel file path based on filePath
|
||||
*/
|
||||
QString getRelFilePath(const QString &filePath)
|
||||
{
|
||||
QString ret;
|
||||
|
||||
int idx = filePath.lastIndexOf(QLatin1Char('/'));
|
||||
if (idx == -1) // not found
|
||||
{
|
||||
// return QString();
|
||||
|
||||
// dev34
|
||||
ret = QLatin1String("_rels/") + QStringLiteral("%0.rels").arg(filePath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = QString(filePath.left(idx) + QLatin1String("/_rels/") + filePath.mid(idx + 1) +
|
||||
QLatin1String(".rels"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
double datetimeToNumber(const QDateTime &dt, bool is1904)
|
||||
{
|
||||
// Note, for number 0, Excel2007 shown as 1900-1-0, which should be 1899-12-31
|
||||
QDateTime epoch(is1904 ? QDate(1904, 1, 1) : QDate(1899, 12, 31), QTime(0, 0));
|
||||
|
||||
double excel_time = epoch.msecsTo(dt) / (1000 * 60 * 60 * 24.0);
|
||||
|
||||
if (dt.isDaylightTime()) // Add one hour if the date is Daylight
|
||||
excel_time += 1.0 / 24.0;
|
||||
|
||||
if (!is1904 && excel_time > 59) { // 31+28
|
||||
// Account for Excel erroneously treating 1900 as a leap year.
|
||||
excel_time += 1;
|
||||
}
|
||||
|
||||
return excel_time;
|
||||
}
|
||||
|
||||
double timeToNumber(const QTime &time)
|
||||
{
|
||||
return QTime(0, 0).msecsTo(time) / (1000 * 60 * 60 * 24.0);
|
||||
}
|
||||
|
||||
QVariant datetimeFromNumber(double num, bool is1904)
|
||||
{
|
||||
static qint64 msecs1904 = QDateTime(QDate(1904, 1, 1), QTime(0, 0)).toMSecsSinceEpoch();
|
||||
static qint64 msecs1899 = QDateTime(QDate(1899, 12, 31), QTime(0, 0)).toMSecsSinceEpoch();
|
||||
|
||||
if (!is1904 && num > 60) // for mac os excel
|
||||
{
|
||||
num = num - 1;
|
||||
}
|
||||
|
||||
auto msecs = static_cast<qint64>(num * 1000 * 60 * 60 * 24.0 + 0.5);
|
||||
|
||||
if (is1904)
|
||||
msecs += msecs1904;
|
||||
else
|
||||
msecs += msecs1899;
|
||||
|
||||
QDateTime dtRet = QDateTime::fromMSecsSinceEpoch(msecs);
|
||||
|
||||
// Remove one hour to see whether the date is Daylight
|
||||
QDateTime dtNew = dtRet.addMSecs(-3600000); // issue102
|
||||
if (dtNew.isDaylightTime()) {
|
||||
dtRet = dtNew;
|
||||
}
|
||||
|
||||
double whole = 0;
|
||||
double fractional = std::modf(num, &whole);
|
||||
|
||||
if (num < double(1)) {
|
||||
// only time
|
||||
QTime t = dtRet.time();
|
||||
return QVariant(t);
|
||||
}
|
||||
|
||||
if (fractional == 0.0) {
|
||||
// only date
|
||||
QDate onlyDT = dtRet.date();
|
||||
return QVariant(onlyDT);
|
||||
}
|
||||
|
||||
return QVariant(dtRet);
|
||||
}
|
||||
|
||||
/*
|
||||
Creates a valid sheet name
|
||||
minimum length is 1
|
||||
maximum length is 31
|
||||
doesn't contain special chars: / \ ? * ] [ :
|
||||
Sheet names must not begin or end with ' (apostrophe)
|
||||
|
||||
Invalid characters are replaced by one space character ' '.
|
||||
*/
|
||||
QString createSafeSheetName(const QString &nameProposal)
|
||||
{
|
||||
if (nameProposal.isEmpty())
|
||||
return QString();
|
||||
|
||||
QString ret = nameProposal;
|
||||
if (nameProposal.length() > 2 && nameProposal.startsWith(QLatin1Char('\'')) &&
|
||||
nameProposal.endsWith(QLatin1Char('\'')))
|
||||
ret = unescapeSheetName(ret);
|
||||
|
||||
// Replace invalid chars with space.
|
||||
static QRegularExpression invalidChars(QStringLiteral("[/\\\\?*\\][:]"));
|
||||
if (nameProposal.contains(invalidChars)) {
|
||||
static QRegularExpression validChars(QStringLiteral("[/\\\\?*\\][:]"));
|
||||
ret.replace(validChars, QStringLiteral(" "));
|
||||
}
|
||||
|
||||
if (ret.startsWith(QLatin1Char('\'')))
|
||||
ret[0] = QLatin1Char(' ');
|
||||
|
||||
if (ret.endsWith(QLatin1Char('\'')))
|
||||
ret[ret.size() - 1] = QLatin1Char(' ');
|
||||
|
||||
if (ret.size() > 31)
|
||||
ret = ret.left(31);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* When sheetName contains space or apostrophe, escaped is needed by
|
||||
* cellFormula/definedName/chartSerials.
|
||||
*/
|
||||
QString escapeSheetName(const QString &sheetName)
|
||||
{
|
||||
// Already escaped.
|
||||
Q_ASSERT(!sheetName.startsWith(QLatin1Char('\'')) && !sheetName.endsWith(QLatin1Char('\'')));
|
||||
|
||||
// These is no need to escape
|
||||
static const auto escape = QRegularExpression(QStringLiteral("[ +\\-,%^=<>'&]"));
|
||||
if (!sheetName.contains(escape))
|
||||
return sheetName;
|
||||
|
||||
// OK, escape is needed.
|
||||
QString name = sheetName;
|
||||
name.replace(QLatin1Char('\''), QLatin1String("\'\'"));
|
||||
return QLatin1Char('\'') + name + QLatin1Char('\'');
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
QString unescapeSheetName(const QString &sheetName)
|
||||
{
|
||||
Q_ASSERT(sheetName.length() > 2 && sheetName.startsWith(QLatin1Char('\'')) &&
|
||||
sheetName.endsWith(QLatin1Char('\'')));
|
||||
|
||||
QString name = sheetName.mid(1, sheetName.length() - 2);
|
||||
name.replace(QLatin1String("\'\'"), QLatin1String("\'"));
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* whether the string s starts or ends with space
|
||||
*/
|
||||
bool isSpaceReserveNeeded(const QString &s)
|
||||
{
|
||||
QString spaces(QStringLiteral(" \t\n\r"));
|
||||
return !s.isEmpty() && (spaces.contains(s.at(0)) || spaces.contains(s.at(s.length() - 1)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert shared formula for non-root cells.
|
||||
*
|
||||
* For example, if "B1:B10" have shared formula "=A1*A1", this function will return "=A2*A2"
|
||||
* for "B2" cell, "=A3*A3" for "B3" cell, etc.
|
||||
*
|
||||
* Note, the formula "=A1*A1" for B1 can also be written as "=RC[-1]*RC[-1]", which is the same
|
||||
* for all other cells. In other words, this formula is shared.
|
||||
*
|
||||
* For long run, we need a formula parser.
|
||||
*/
|
||||
QString convertSharedFormula(const QString &rootFormula,
|
||||
const CellReference &rootCell,
|
||||
const CellReference &cell)
|
||||
{
|
||||
Q_UNUSED(rootCell)
|
||||
Q_UNUSED(cell)
|
||||
// Find all the "$?[A-Z]+$?[0-9]+" patterns in the rootFormula.
|
||||
QVector<std::pair<QString, int>> segments;
|
||||
|
||||
QString segment;
|
||||
bool inQuote = false;
|
||||
enum RefState { INVALID, PRE_AZ, AZ, PRE_09, _09 };
|
||||
RefState refState = INVALID;
|
||||
int refFlag = 0; // 0x00, 0x01, 0x02, 0x03 ==> A1, $A1, A$1, $A$1
|
||||
for (QChar ch : rootFormula) {
|
||||
if (inQuote) {
|
||||
segment.append(ch);
|
||||
if (ch == QLatin1Char('"'))
|
||||
inQuote = false;
|
||||
} else {
|
||||
if (ch == QLatin1Char('"')) {
|
||||
inQuote = true;
|
||||
refState = INVALID;
|
||||
segment.append(ch);
|
||||
} else if (ch == QLatin1Char('$')) {
|
||||
if (refState == AZ) {
|
||||
segment.append(ch);
|
||||
refState = PRE_09;
|
||||
refFlag |= 0x02;
|
||||
} else {
|
||||
segments.append(std::make_pair(segment, refState == _09 ? refFlag : -1));
|
||||
segment = QString(ch); // Start new segment.
|
||||
refState = PRE_AZ;
|
||||
refFlag = 0x01;
|
||||
}
|
||||
} else if (ch >= QLatin1Char('A') && ch <= QLatin1Char('Z')) {
|
||||
if (refState == PRE_AZ || refState == AZ) {
|
||||
segment.append(ch);
|
||||
} else {
|
||||
segments.append(std::make_pair(segment, refState == _09 ? refFlag : -1));
|
||||
segment = QString(ch); // Start new segment.
|
||||
refFlag = 0x00;
|
||||
}
|
||||
refState = AZ;
|
||||
} else if (ch >= QLatin1Char('0') && ch <= QLatin1Char('9')) {
|
||||
segment.append(ch);
|
||||
|
||||
if (refState == AZ || refState == PRE_09 || refState == _09)
|
||||
refState = _09;
|
||||
else
|
||||
refState = INVALID;
|
||||
} else {
|
||||
if (refState == _09) {
|
||||
segments.append(std::make_pair(segment, refFlag));
|
||||
segment = QString(ch); // Start new segment.
|
||||
} else {
|
||||
segment.append(ch);
|
||||
}
|
||||
refState = INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!segment.isEmpty())
|
||||
segments.append(std::make_pair(segment, refState == _09 ? refFlag : -1));
|
||||
|
||||
// Replace "A1", "$A1", "A$1" segment with proper one.
|
||||
QStringList result;
|
||||
for (const auto &p : segments) {
|
||||
// qDebug()<<p.first<<p.second;
|
||||
if (p.second != -1 && p.second != 3) {
|
||||
CellReference oldRef(p.first);
|
||||
int row = p.second & 0x02 ? oldRef.row() : oldRef.row() - rootCell.row() + cell.row();
|
||||
int col = p.second & 0x01 ? oldRef.column()
|
||||
: oldRef.column() - rootCell.column() + cell.column();
|
||||
result.append(CellReference(row, col).toString(p.second & 0x02, p.second & 0x01));
|
||||
} else {
|
||||
result.append(p.first);
|
||||
}
|
||||
}
|
||||
|
||||
// OK
|
||||
return result.join(QString());
|
||||
}
|
||||
|
||||
QString xsdBoolean(bool value)
|
||||
{
|
||||
return value ? QStringLiteral("1") : QStringLiteral("0");
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,736 @@
|
|||
// xlsxworkbook.cpp
|
||||
|
||||
#include "xlsxworkbook.h"
|
||||
|
||||
#include "xlsxchart.h"
|
||||
#include "xlsxchartsheet.h"
|
||||
#include "xlsxformat.h"
|
||||
#include "xlsxformat_p.h"
|
||||
#include "xlsxmediafile_p.h"
|
||||
#include "xlsxsharedstrings_p.h"
|
||||
#include "xlsxstyles_p.h"
|
||||
#include "xlsxutility_p.h"
|
||||
#include "xlsxworkbook_p.h"
|
||||
#include "xlsxworksheet.h"
|
||||
#include "xlsxworksheet_p.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QtDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
WorkbookPrivate::WorkbookPrivate(Workbook *q, Workbook::CreateFlag flag)
|
||||
: AbstractOOXmlFilePrivate(q, flag)
|
||||
{
|
||||
sharedStrings = std::make_shared<SharedStrings>(flag);
|
||||
styles = std::make_shared<Styles>(flag);
|
||||
theme = std::make_shared<Theme>(flag);
|
||||
|
||||
x_window = 240;
|
||||
y_window = 15;
|
||||
window_width = 16095;
|
||||
window_height = 9660;
|
||||
|
||||
strings_to_numbers_enabled = false;
|
||||
strings_to_hyperlinks_enabled = true;
|
||||
html_to_richstring_enabled = false;
|
||||
date1904 = false;
|
||||
defaultDateFormat = QStringLiteral("yyyy-mm-dd");
|
||||
activesheetIndex = 0;
|
||||
firstsheet = 0;
|
||||
table_count = 0;
|
||||
|
||||
last_worksheet_index = 0;
|
||||
last_chartsheet_index = 0;
|
||||
last_sheet_id = 0;
|
||||
}
|
||||
|
||||
Workbook::Workbook(CreateFlag flag)
|
||||
: AbstractOOXmlFile(new WorkbookPrivate(this, flag))
|
||||
{
|
||||
}
|
||||
|
||||
Workbook::~Workbook()
|
||||
{
|
||||
}
|
||||
|
||||
bool Workbook::isDate1904() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
return d->date1904;
|
||||
}
|
||||
|
||||
/*!
|
||||
Excel for Windows uses a default epoch of 1900 and Excel
|
||||
for Mac uses an epoch of 1904. However, Excel on either
|
||||
platform will convert automatically between one system
|
||||
and the other. Qt Xlsx stores dates in the 1900 format
|
||||
by default.
|
||||
|
||||
\note This function should be called before any date/time
|
||||
has been written.
|
||||
*/
|
||||
void Workbook::setDate1904(bool date1904)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
d->date1904 = date1904;
|
||||
}
|
||||
|
||||
/*
|
||||
Enable the worksheet.write() method to convert strings
|
||||
to numbers, where possible, using float() in order to avoid
|
||||
an Excel warning about "Numbers Stored as Text".
|
||||
|
||||
The default is false
|
||||
*/
|
||||
void Workbook::setStringsToNumbersEnabled(bool enable)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
d->strings_to_numbers_enabled = enable;
|
||||
}
|
||||
|
||||
bool Workbook::isStringsToNumbersEnabled() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
return d->strings_to_numbers_enabled;
|
||||
}
|
||||
|
||||
void Workbook::setStringsToHyperlinksEnabled(bool enable)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
d->strings_to_hyperlinks_enabled = enable;
|
||||
}
|
||||
|
||||
bool Workbook::isStringsToHyperlinksEnabled() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
return d->strings_to_hyperlinks_enabled;
|
||||
}
|
||||
|
||||
void Workbook::setHtmlToRichStringEnabled(bool enable)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
d->html_to_richstring_enabled = enable;
|
||||
}
|
||||
|
||||
bool Workbook::isHtmlToRichStringEnabled() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
return d->html_to_richstring_enabled;
|
||||
}
|
||||
|
||||
QString Workbook::defaultDateFormat() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
return d->defaultDateFormat;
|
||||
}
|
||||
|
||||
void Workbook::setDefaultDateFormat(const QString &format)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
d->defaultDateFormat = format;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Create a defined name in the workbook.
|
||||
* \param name The defined name
|
||||
* \param formula The cell or range that the defined name refers to.
|
||||
* \param comment
|
||||
* \param scope The name of one worksheet, or empty which means global scope.
|
||||
* \return Return false if the name invalid.
|
||||
*/
|
||||
bool Workbook::defineName(const QString &name,
|
||||
const QString &formula,
|
||||
const QString &comment,
|
||||
const QString &scope)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
|
||||
// Remove the = sign from the formula if it exists.
|
||||
QString formulaString = formula;
|
||||
if (formulaString.startsWith(QLatin1Char('=')))
|
||||
formulaString = formula.mid(1);
|
||||
|
||||
int id = -1;
|
||||
if (!scope.isEmpty()) {
|
||||
for (int i = 0; i < d->sheets.size(); ++i) {
|
||||
if (d->sheets[i]->sheetName() == scope) {
|
||||
id = d->sheets[i]->sheetId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d->definedNamesList.append(XlsxDefineNameData(name, formulaString, comment, id));
|
||||
return true;
|
||||
}
|
||||
|
||||
AbstractSheet *Workbook::addSheet(const QString &name, AbstractSheet::SheetType type)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
return insertSheet(d->sheets.size(), name, type);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
QStringList Workbook::worksheetNames() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
return d->sheetNames;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* Used only when load the xlsx file!!
|
||||
*/
|
||||
AbstractSheet *Workbook::addSheet(const QString &name, int sheetId, AbstractSheet::SheetType type)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
if (sheetId > d->last_sheet_id)
|
||||
d->last_sheet_id = sheetId;
|
||||
|
||||
AbstractSheet *sheet = nullptr;
|
||||
if (type == AbstractSheet::ST_WorkSheet) {
|
||||
// create work sheet (value sheet)
|
||||
sheet = new Worksheet(name, sheetId, this, F_LoadFromExists);
|
||||
} else if (type == AbstractSheet::ST_ChartSheet) {
|
||||
// create chart sheet
|
||||
sheet = new Chartsheet(name, sheetId, this, F_LoadFromExists);
|
||||
} else {
|
||||
qWarning("unsupported sheet type.");
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
||||
d->sheets.append(std::shared_ptr<AbstractSheet>(sheet));
|
||||
d->sheetNames.append(name);
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
AbstractSheet *Workbook::insertSheet(int index, const QString &name, AbstractSheet::SheetType type)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
QString sheetName = createSafeSheetName(name);
|
||||
if (index > d->last_sheet_id) {
|
||||
// User tries to insert, where no sheet has gone before.
|
||||
return nullptr;
|
||||
}
|
||||
if (!sheetName.isEmpty()) {
|
||||
// If user given an already in-used name, we should not continue any more!
|
||||
if (d->sheetNames.contains(sheetName))
|
||||
return nullptr;
|
||||
} else {
|
||||
if (type == AbstractSheet::ST_WorkSheet) {
|
||||
do {
|
||||
++d->last_worksheet_index;
|
||||
sheetName = QStringLiteral("Sheet%1").arg(d->last_worksheet_index);
|
||||
} while (d->sheetNames.contains(sheetName));
|
||||
} else if (type == AbstractSheet::ST_ChartSheet) {
|
||||
do {
|
||||
++d->last_chartsheet_index;
|
||||
sheetName = QStringLiteral("Chart%1").arg(d->last_chartsheet_index);
|
||||
} while (d->sheetNames.contains(sheetName));
|
||||
} else {
|
||||
qWarning("unsupported sheet type.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
++d->last_sheet_id;
|
||||
|
||||
AbstractSheet *sheet = nullptr;
|
||||
if (type == AbstractSheet::ST_WorkSheet) {
|
||||
sheet = new Worksheet(sheetName, d->last_sheet_id, this, F_NewFromScratch);
|
||||
} else if (type == AbstractSheet::ST_ChartSheet) {
|
||||
sheet = new Chartsheet(sheetName, d->last_sheet_id, this, F_NewFromScratch);
|
||||
} else {
|
||||
qWarning("unsupported sheet type.");
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
||||
d->sheets.insert(index, std::shared_ptr<AbstractSheet>(sheet));
|
||||
d->sheetNames.insert(index, sheetName);
|
||||
d->activesheetIndex = index;
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns current active worksheet.
|
||||
*/
|
||||
AbstractSheet *Workbook::activeSheet() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
if (d->sheets.isEmpty())
|
||||
const_cast<Workbook *>(this)->addSheet();
|
||||
return d->sheets[d->activesheetIndex].get();
|
||||
}
|
||||
|
||||
bool Workbook::setActiveSheet(int index)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
if (index < 0 || index >= d->sheets.size()) {
|
||||
// warning
|
||||
return false;
|
||||
}
|
||||
d->activesheetIndex = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Rename the worksheet at the \a index to \a newName.
|
||||
*/
|
||||
bool Workbook::renameSheet(int index, const QString &newName)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
QString name = createSafeSheetName(newName);
|
||||
if (index < 0 || index >= d->sheets.size())
|
||||
return false;
|
||||
|
||||
// If user given an already in-used name, return false
|
||||
for (int i = 0; i < d->sheets.size(); ++i) {
|
||||
if (d->sheets[i]->sheetName() == name)
|
||||
return false;
|
||||
}
|
||||
|
||||
d->sheets[index]->setSheetName(name);
|
||||
d->sheetNames[index] = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Remove the worksheet at pos \a index.
|
||||
*/
|
||||
bool Workbook::deleteSheet(int index)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
if (d->sheets.size() <= 1)
|
||||
return false;
|
||||
if (index < 0 || index >= d->sheets.size())
|
||||
return false;
|
||||
d->sheets.removeAt(index);
|
||||
d->sheetNames.removeAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Moves the worksheet form \a srcIndex to \a distIndex.
|
||||
*/
|
||||
bool Workbook::moveSheet(int srcIndex, int distIndex)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
if (srcIndex == distIndex)
|
||||
return false;
|
||||
|
||||
if (srcIndex < 0 || srcIndex >= d->sheets.size())
|
||||
return false;
|
||||
|
||||
std::shared_ptr<AbstractSheet> sheet = d->sheets.takeAt(srcIndex);
|
||||
d->sheetNames.takeAt(srcIndex);
|
||||
if (distIndex >= 0 || distIndex <= d->sheets.size()) {
|
||||
d->sheets.insert(distIndex, sheet);
|
||||
d->sheetNames.insert(distIndex, sheet->sheetName());
|
||||
} else {
|
||||
d->sheets.append(sheet);
|
||||
d->sheetNames.append(sheet->sheetName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Workbook::copySheet(int index, const QString &newName)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
if (index < 0 || index >= d->sheets.size())
|
||||
return false;
|
||||
|
||||
QString worksheetName = createSafeSheetName(newName);
|
||||
if (!newName.isEmpty()) {
|
||||
// If user given an already in-used name, we should not continue any more!
|
||||
if (d->sheetNames.contains(newName))
|
||||
return false;
|
||||
} else {
|
||||
int copy_index = 1;
|
||||
do {
|
||||
++copy_index;
|
||||
worksheetName =
|
||||
QStringLiteral("%1(%2)").arg(d->sheets[index]->sheetName()).arg(copy_index);
|
||||
} while (d->sheetNames.contains(worksheetName));
|
||||
}
|
||||
|
||||
++d->last_sheet_id;
|
||||
AbstractSheet *sheet = d->sheets[index]->copy(worksheetName, d->last_sheet_id);
|
||||
d->sheets.append(std::shared_ptr<AbstractSheet>(sheet));
|
||||
d->sheetNames.append(sheet->sheetName());
|
||||
|
||||
return true; // #162
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns count of worksheets.
|
||||
*/
|
||||
int Workbook::sheetCount() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
return d->sheets.count();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the sheet object at index \a sheetIndex.
|
||||
*/
|
||||
AbstractSheet *Workbook::sheet(int index) const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
if (index < 0 || index >= d->sheets.size())
|
||||
return nullptr;
|
||||
return d->sheets.at(index).get();
|
||||
}
|
||||
|
||||
SharedStrings *Workbook::sharedStrings() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
return d->sharedStrings.get();
|
||||
}
|
||||
|
||||
Styles *Workbook::styles()
|
||||
{
|
||||
Q_D(Workbook);
|
||||
return d->styles.get();
|
||||
}
|
||||
|
||||
Theme *Workbook::theme()
|
||||
{
|
||||
Q_D(Workbook);
|
||||
return d->theme.get();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*
|
||||
* Unlike media files, drawing file is a property of the sheet.
|
||||
*/
|
||||
QList<Drawing *> Workbook::drawings()
|
||||
{
|
||||
Q_D(Workbook);
|
||||
QList<Drawing *> ds;
|
||||
for (int i = 0; i < d->sheets.size(); ++i) {
|
||||
std::shared_ptr<AbstractSheet> sheet = d->sheets[i];
|
||||
if (sheet->drawing())
|
||||
ds.append(sheet->drawing());
|
||||
}
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
QList<std::shared_ptr<AbstractSheet>>
|
||||
Workbook::getSheetsByTypes(AbstractSheet::SheetType type) const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
QList<std::shared_ptr<AbstractSheet>> list;
|
||||
for (int i = 0; i < d->sheets.size(); ++i) {
|
||||
if (d->sheets[i]->sheetType() == type)
|
||||
list.append(d->sheets[i]);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void Workbook::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
d->relationships->clear();
|
||||
if (d->sheets.isEmpty())
|
||||
const_cast<Workbook *>(this)->addSheet();
|
||||
|
||||
QXmlStreamWriter writer(device);
|
||||
|
||||
writer.writeStartDocument(QStringLiteral("1.0"), true);
|
||||
writer.writeStartElement(QStringLiteral("workbook"));
|
||||
writer.writeAttribute(
|
||||
QStringLiteral("xmlns"),
|
||||
QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main"));
|
||||
writer.writeAttribute(
|
||||
QStringLiteral("xmlns:r"),
|
||||
QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
|
||||
|
||||
writer.writeEmptyElement(QStringLiteral("fileVersion"));
|
||||
writer.writeAttribute(QStringLiteral("appName"), QStringLiteral("xl"));
|
||||
writer.writeAttribute(QStringLiteral("lastEdited"), QStringLiteral("4"));
|
||||
writer.writeAttribute(QStringLiteral("lowestEdited"), QStringLiteral("4"));
|
||||
writer.writeAttribute(QStringLiteral("rupBuild"), QStringLiteral("4505"));
|
||||
// writer.writeAttribute(QStringLiteral("codeName"),
|
||||
// QStringLiteral("{37E998C4-C9E5-D4B9-71C8-EB1FF731991C}"));
|
||||
|
||||
writer.writeEmptyElement(QStringLiteral("workbookPr"));
|
||||
if (d->date1904)
|
||||
writer.writeAttribute(QStringLiteral("date1904"), QStringLiteral("1"));
|
||||
writer.writeAttribute(QStringLiteral("defaultThemeVersion"), QStringLiteral("124226"));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("bookViews"));
|
||||
writer.writeEmptyElement(QStringLiteral("workbookView"));
|
||||
writer.writeAttribute(QStringLiteral("xWindow"), QString::number(d->x_window));
|
||||
writer.writeAttribute(QStringLiteral("yWindow"), QString::number(d->y_window));
|
||||
writer.writeAttribute(QStringLiteral("windowWidth"), QString::number(d->window_width));
|
||||
writer.writeAttribute(QStringLiteral("windowHeight"), QString::number(d->window_height));
|
||||
// Store the firstSheet when it isn't the default
|
||||
// For example, when "the first sheet 0 is hidden", the first sheet will be 1
|
||||
if (d->firstsheet > 0)
|
||||
writer.writeAttribute(QStringLiteral("firstSheet"), QString::number(d->firstsheet + 1));
|
||||
// Store the activeTab when it isn't the first sheet
|
||||
if (d->activesheetIndex > 0)
|
||||
writer.writeAttribute(QStringLiteral("activeTab"), QString::number(d->activesheetIndex));
|
||||
writer.writeEndElement(); // bookViews
|
||||
|
||||
writer.writeStartElement(QStringLiteral("sheets"));
|
||||
int worksheetIndex = 0;
|
||||
int chartsheetIndex = 0;
|
||||
for (int i = 0; i < d->sheets.size(); ++i) {
|
||||
std::shared_ptr<AbstractSheet> sheet = d->sheets[i];
|
||||
writer.writeEmptyElement(QStringLiteral("sheet"));
|
||||
writer.writeAttribute(QStringLiteral("name"), sheet->sheetName());
|
||||
writer.writeAttribute(QStringLiteral("sheetId"), QString::number(sheet->sheetId()));
|
||||
if (sheet->sheetState() == AbstractSheet::SS_Hidden)
|
||||
writer.writeAttribute(QStringLiteral("state"), QStringLiteral("hidden"));
|
||||
else if (sheet->sheetState() == AbstractSheet::SS_VeryHidden)
|
||||
writer.writeAttribute(QStringLiteral("state"), QStringLiteral("veryHidden"));
|
||||
|
||||
if (sheet->sheetType() == AbstractSheet::ST_WorkSheet)
|
||||
d->relationships->addDocumentRelationship(
|
||||
QStringLiteral("/worksheet"),
|
||||
QStringLiteral("worksheets/sheet%1.xml").arg(++worksheetIndex));
|
||||
else
|
||||
d->relationships->addDocumentRelationship(
|
||||
QStringLiteral("/chartsheet"),
|
||||
QStringLiteral("chartsheets/sheet%1.xml").arg(++chartsheetIndex));
|
||||
|
||||
writer.writeAttribute(QStringLiteral("r:id"),
|
||||
QStringLiteral("rId%1").arg(d->relationships->count()));
|
||||
}
|
||||
writer.writeEndElement(); // sheets
|
||||
|
||||
if (!d->externalLinks.isEmpty()) {
|
||||
writer.writeStartElement(QStringLiteral("externalReferences"));
|
||||
for (int i = 0; i < d->externalLinks.size(); ++i) {
|
||||
writer.writeEmptyElement(QStringLiteral("externalReference"));
|
||||
d->relationships->addDocumentRelationship(
|
||||
QStringLiteral("/externalLink"),
|
||||
QStringLiteral("externalLinks/externalLink%1.xml").arg(i + 1));
|
||||
writer.writeAttribute(QStringLiteral("r:id"),
|
||||
QStringLiteral("rId%1").arg(d->relationships->count()));
|
||||
}
|
||||
writer.writeEndElement(); // externalReferences
|
||||
}
|
||||
|
||||
if (!d->definedNamesList.isEmpty()) {
|
||||
writer.writeStartElement(QStringLiteral("definedNames"));
|
||||
for (const XlsxDefineNameData &data : d->definedNamesList) {
|
||||
writer.writeStartElement(QStringLiteral("definedName"));
|
||||
writer.writeAttribute(QStringLiteral("name"), data.name);
|
||||
if (!data.comment.isEmpty())
|
||||
writer.writeAttribute(QStringLiteral("comment"), data.comment);
|
||||
if (data.sheetId != -1) {
|
||||
// find the local index of the sheet.
|
||||
for (int i = 0; i < d->sheets.size(); ++i) {
|
||||
if (d->sheets[i]->sheetId() == data.sheetId) {
|
||||
writer.writeAttribute(QStringLiteral("localSheetId"), QString::number(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
writer.writeCharacters(data.formula);
|
||||
writer.writeEndElement(); // definedName
|
||||
}
|
||||
writer.writeEndElement(); // definedNames
|
||||
}
|
||||
|
||||
writer.writeStartElement(QStringLiteral("calcPr"));
|
||||
writer.writeAttribute(QStringLiteral("calcId"), QStringLiteral("124519"));
|
||||
writer.writeEndElement(); // calcPr
|
||||
|
||||
writer.writeEndElement(); // workbook
|
||||
writer.writeEndDocument();
|
||||
|
||||
d->relationships->addDocumentRelationship(QStringLiteral("/theme"),
|
||||
QStringLiteral("theme/theme1.xml"));
|
||||
d->relationships->addDocumentRelationship(QStringLiteral("/styles"),
|
||||
QStringLiteral("styles.xml"));
|
||||
if (!sharedStrings()->isEmpty())
|
||||
d->relationships->addDocumentRelationship(QStringLiteral("/sharedStrings"),
|
||||
QStringLiteral("sharedStrings.xml"));
|
||||
}
|
||||
|
||||
bool Workbook::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
|
||||
QXmlStreamReader reader(device);
|
||||
while (!reader.atEnd()) {
|
||||
QXmlStreamReader::TokenType token = reader.readNext();
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("sheet")) {
|
||||
QXmlStreamAttributes attributes = reader.attributes();
|
||||
|
||||
const auto &name = attributes.value(QLatin1String("name")).toString();
|
||||
|
||||
int sheetId = attributes.value(QLatin1String("sheetId")).toInt();
|
||||
|
||||
const auto &rId = attributes.value(QLatin1String("r:id")).toString();
|
||||
|
||||
const auto &stateString = attributes.value(QLatin1String("state"));
|
||||
|
||||
AbstractSheet::SheetState state = AbstractSheet::SS_Visible;
|
||||
if (stateString == QLatin1String("hidden"))
|
||||
state = AbstractSheet::SS_Hidden;
|
||||
else if (stateString == QLatin1String("veryHidden"))
|
||||
state = AbstractSheet::SS_VeryHidden;
|
||||
|
||||
XlsxRelationship relationship = d->relationships->getRelationshipById(rId);
|
||||
|
||||
AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet;
|
||||
if (relationship.type.endsWith(QLatin1String("/worksheet"))) {
|
||||
type = AbstractSheet::ST_WorkSheet;
|
||||
} else if (relationship.type.endsWith(QLatin1String("/chartsheet"))) {
|
||||
type = AbstractSheet::ST_ChartSheet;
|
||||
} else if (relationship.type.endsWith(QLatin1String("/dialogsheet"))) {
|
||||
type = AbstractSheet::ST_DialogSheet;
|
||||
} else if (relationship.type.endsWith(QLatin1String("/xlMacrosheet"))) {
|
||||
type = AbstractSheet::ST_MacroSheet;
|
||||
} else {
|
||||
qWarning() << "unknown sheet type : " << relationship.type;
|
||||
}
|
||||
|
||||
AbstractSheet *sheet = addSheet(name, sheetId, type);
|
||||
sheet->setSheetState(state);
|
||||
if (relationship.target.startsWith(u'/')) {
|
||||
QString fullPath = QDir::cleanPath(relationship.target.mid(1));
|
||||
|
||||
sheet->setFilePath(fullPath);
|
||||
} else {
|
||||
QString strFilePath = filePath();
|
||||
|
||||
// const QString fullPath = QDir::cleanPath(splitPath(strFilePath).constFirst()
|
||||
// + QLatin1String("/") + relationship.target);
|
||||
const auto parts = splitPath(strFilePath);
|
||||
QString fullPath = QDir::cleanPath(parts.first() + u'/' + relationship.target);
|
||||
|
||||
sheet->setFilePath(fullPath);
|
||||
}
|
||||
} else if (reader.name() == QLatin1String("workbookPr")) {
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
if (attrs.hasAttribute(QLatin1String("date1904")))
|
||||
d->date1904 = true;
|
||||
} else if (reader.name() == QLatin1String("bookviews")) {
|
||||
while (!(reader.name() == QLatin1String("bookviews") &&
|
||||
reader.tokenType() == QXmlStreamReader::EndElement)) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("workbookView")) {
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
if (attrs.hasAttribute(QLatin1String("xWindow")))
|
||||
d->x_window = attrs.value(QLatin1String("xWindow")).toInt();
|
||||
if (attrs.hasAttribute(QLatin1String("yWindow")))
|
||||
d->y_window = attrs.value(QLatin1String("yWindow")).toInt();
|
||||
if (attrs.hasAttribute(QLatin1String("windowWidth")))
|
||||
d->window_width = attrs.value(QLatin1String("windowWidth")).toInt();
|
||||
if (attrs.hasAttribute(QLatin1String("windowHeight")))
|
||||
d->window_height =
|
||||
attrs.value(QLatin1String("windowHeight")).toInt();
|
||||
if (attrs.hasAttribute(QLatin1String("firstSheet")))
|
||||
d->firstsheet = attrs.value(QLatin1String("firstSheet")).toInt();
|
||||
if (attrs.hasAttribute(QLatin1String("activeTab")))
|
||||
d->activesheetIndex =
|
||||
attrs.value(QLatin1String("activeTab")).toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (reader.name() == QLatin1String("externalReference")) {
|
||||
QXmlStreamAttributes attributes = reader.attributes();
|
||||
const QString rId = attributes.value(QLatin1String("r:id")).toString();
|
||||
XlsxRelationship relationship = d->relationships->getRelationshipById(rId);
|
||||
|
||||
std::shared_ptr<SimpleOOXmlFile> link(new SimpleOOXmlFile(F_LoadFromExists));
|
||||
|
||||
const auto parts = splitPath(filePath());
|
||||
QString fullPath =
|
||||
QDir::cleanPath(parts.first() + QLatin1String("/") + relationship.target);
|
||||
|
||||
link->setFilePath(fullPath);
|
||||
d->externalLinks.append(link);
|
||||
} else if (reader.name() == QLatin1String("definedName")) {
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
XlsxDefineNameData data;
|
||||
|
||||
data.name = attrs.value(QLatin1String("name")).toString();
|
||||
if (attrs.hasAttribute(QLatin1String("comment")))
|
||||
data.comment = attrs.value(QLatin1String("comment")).toString();
|
||||
if (attrs.hasAttribute(QLatin1String("localSheetId"))) {
|
||||
int localId = attrs.value(QLatin1String("localSheetId")).toInt();
|
||||
int sheetId = d->sheets.at(localId)->sheetId();
|
||||
data.sheetId = sheetId;
|
||||
}
|
||||
data.formula = reader.readElementText();
|
||||
d->definedNamesList.append(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
QList<std::shared_ptr<MediaFile>> Workbook::mediaFiles() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
|
||||
return d->mediaFiles;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
void Workbook::addMediaFile(std::shared_ptr<MediaFile> media, bool force)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
|
||||
if (!force) {
|
||||
for (int i = 0; i < d->mediaFiles.size(); ++i) {
|
||||
if (d->mediaFiles[i]->hashKey() == media->hashKey()) {
|
||||
media->setIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
media->setIndex(d->mediaFiles.size());
|
||||
d->mediaFiles.append(media);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
QList<std::shared_ptr<Chart>> Workbook::chartFiles() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
|
||||
return d->chartFiles;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
void Workbook::addChartFile(std::shared_ptr<Chart> chart)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
|
||||
if (!d->chartFiles.contains(chart))
|
||||
d->chartFiles.append(chart);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,49 @@
|
|||
// xlsxzipreader.cpp
|
||||
|
||||
#include "xlsxzipreader_p.h"
|
||||
|
||||
#include <private/qzipreader_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
ZipReader::ZipReader(const QString &filePath)
|
||||
: m_reader(new QZipReader(filePath))
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
ZipReader::ZipReader(QIODevice *device)
|
||||
: m_reader(new QZipReader(device))
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
ZipReader::~ZipReader()
|
||||
{
|
||||
}
|
||||
|
||||
void ZipReader::init()
|
||||
{
|
||||
const auto &allFiles = m_reader->fileInfoList();
|
||||
for (const auto &fi : allFiles) {
|
||||
if (fi.isFile || (!fi.isDir && !fi.isFile && !fi.isSymLink))
|
||||
m_filePaths.append(fi.filePath);
|
||||
}
|
||||
}
|
||||
|
||||
bool ZipReader::exists() const
|
||||
{
|
||||
return m_reader->exists();
|
||||
}
|
||||
|
||||
QStringList ZipReader::filePaths() const
|
||||
{
|
||||
return m_filePaths;
|
||||
}
|
||||
|
||||
QByteArray ZipReader::fileData(const QString &fileName) const
|
||||
{
|
||||
return m_reader->fileData(fileName);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -0,0 +1,48 @@
|
|||
// xlsxzipwriter.cpp
|
||||
|
||||
#include "xlsxzipwriter_p.h"
|
||||
|
||||
#include <private/qzipwriter_p.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
ZipWriter::ZipWriter(const QString &filePath)
|
||||
{
|
||||
m_writer = new QZipWriter(filePath, QIODevice::WriteOnly);
|
||||
m_writer->setCompressionPolicy(QZipWriter::AutoCompress);
|
||||
}
|
||||
|
||||
ZipWriter::ZipWriter(QIODevice *device)
|
||||
{
|
||||
m_writer = new QZipWriter(device);
|
||||
m_writer->setCompressionPolicy(QZipWriter::AutoCompress);
|
||||
}
|
||||
|
||||
ZipWriter::~ZipWriter()
|
||||
{
|
||||
delete m_writer;
|
||||
}
|
||||
|
||||
bool ZipWriter::error() const
|
||||
{
|
||||
return m_writer->status() != QZipWriter::NoError;
|
||||
}
|
||||
|
||||
void ZipWriter::addFile(const QString &filePath, QIODevice *device)
|
||||
{
|
||||
m_writer->addFile(filePath, device);
|
||||
}
|
||||
|
||||
void ZipWriter::addFile(const QString &filePath, const QByteArray &data)
|
||||
{
|
||||
m_writer->addFile(filePath, data);
|
||||
}
|
||||
|
||||
void ZipWriter::close()
|
||||
{
|
||||
m_writer->close();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
|
@ -104,7 +104,11 @@ CtrlHdmiPanel::CtrlHdmiPanel() {
|
|||
json.insert("_type", "AutoSyncSwitch");
|
||||
json.insert("isAuto", edAutoSwitch->isChecked());
|
||||
if(gSelCards.count() == 1) {
|
||||
if(gSelCards[0].id.startsWith("g", Qt::CaseInsensitive)) {
|
||||
if(gSelCards[0].id.startsWith("g", Qt::CaseInsensitive)
|
||||
|| gSelCards[0].id.startsWith("m8h", Qt::CaseInsensitive)
|
||||
|| gSelCards[0].id.startsWith("m8s", Qt::CaseInsensitive)
|
||||
|| gSelCards[0].id.startsWith("y8h", Qt::CaseInsensitive)
|
||||
) {
|
||||
auto waitingDlg = new WaitingDlg(this, tr("SyncSwitch"));
|
||||
Def_CtrlReqPre
|
||||
connect(reply, &QNetworkReply::finished, this, [=] {
|
||||
|
@ -112,7 +116,11 @@ CtrlHdmiPanel::CtrlHdmiPanel() {
|
|||
});
|
||||
}
|
||||
} else {
|
||||
for(auto &card : gSelCards) if(card.id.startsWith("g", Qt::CaseInsensitive)) {
|
||||
for(auto &card : gSelCards) if(card.id.startsWith("g", Qt::CaseInsensitive)
|
||||
|| card.id.startsWith("m8h", Qt::CaseInsensitive)
|
||||
|| card.id.startsWith("m8s", Qt::CaseInsensitive)
|
||||
|| card.id.startsWith("y8h", Qt::CaseInsensitive)
|
||||
) {
|
||||
Def_CtrlSetMulti(tr("SyncSwitch"))
|
||||
}
|
||||
}
|
||||
|
@ -347,7 +355,10 @@ void CtrlHdmiPanel::init() {
|
|||
return;
|
||||
}
|
||||
auto card = gSelCards[0];
|
||||
auto needShow = card.id.startsWith("g", Qt::CaseInsensitive) || card.id.startsWith("m8s", Qt::CaseInsensitive);
|
||||
auto needShow = card.id.startsWith("g", Qt::CaseInsensitive)
|
||||
|| card.id.startsWith("m8h", Qt::CaseInsensitive)
|
||||
|| card.id.startsWith("m8s", Qt::CaseInsensitive)
|
||||
|| card.id.startsWith("y8h", Qt::CaseInsensitive);
|
||||
fdHdmi2->setVisible(needShow);
|
||||
edAutoSwitch->setVisible(needShow);
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "gutil/qnetwork.h"
|
||||
#include "main.h"
|
||||
#include "gutil/qgui.h"
|
||||
#include "tools.h"
|
||||
#include <QMessageBox>
|
||||
#include <QTimeZone>
|
||||
#include <QLineEdit>
|
||||
|
|
|
@ -52,8 +52,9 @@ void EBase::setBaseAttr(const JObj &json) {
|
|||
mExitEffect = json["exitEffect"].toStr();
|
||||
mEntryDur = json["entryDur"].toInt();
|
||||
mExitDur = json["exitDur"].toInt();
|
||||
_rotate = json["rotate"].toInt();
|
||||
_opacity = json["opacity"].toDouble(1);
|
||||
setTransformOriginPoint(mWidth/2, mHeight/2);
|
||||
setRotation(json["rotate"].toDouble());
|
||||
setOpacity(json["opacity"].toDouble(1));
|
||||
_blink = json["blink"].toDouble(1);
|
||||
_hasBlink = json["hasBlink"].toBool();
|
||||
_hasBreathe = json["hasBreathe"].toBool();
|
||||
|
@ -88,8 +89,8 @@ void EBase::addBaseAttr(JObj &obj) const {
|
|||
obj.insert("exitEffect", mExitEffect);
|
||||
obj.insert("entryDur", mEntryDur);
|
||||
obj.insert("exitDur", mExitDur);
|
||||
obj["rotate"] = _rotate;
|
||||
obj["opacity"] = _opacity;
|
||||
obj["rotate"] = rotation();
|
||||
obj["opacity"] = opacity();
|
||||
obj["blink"] = _blink;
|
||||
obj["hasBlink"] = _hasBlink;
|
||||
obj["hasBreathe"] = _hasBreathe;
|
||||
|
@ -113,6 +114,7 @@ void EBase::fitProgSize() {
|
|||
prepareGeometryChange();
|
||||
mWidth *= rate;
|
||||
mHeight *= rate;
|
||||
setTransformOriginPoint(mWidth/2, mHeight/2);
|
||||
emit sizeChanged();
|
||||
}
|
||||
int lmt = gProgItem->mWidth - mWidth;
|
||||
|
@ -125,11 +127,10 @@ QRectF EBase::boundingRect() const {
|
|||
qreal xy = -m_handleLen / 2;
|
||||
return QRectF(xy, xy, mWidth + m_handleLen, mHeight + m_handleLen);
|
||||
}
|
||||
//绘制选中和未选中的区域边框
|
||||
|
||||
void EBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
|
||||
if(mMultiWin!=nullptr) return;
|
||||
if(mMultiWin) return;
|
||||
painter->save();
|
||||
//绘制边框
|
||||
if(bdImgIdx > -1) {
|
||||
if(bdTimerId==0 && !bdEff.isEmpty()) {
|
||||
if(bdEff.startsWith("ro")) bdTimerId = startTimer(bdSpeed==1 ? 66 : (bdSpeed==2 ? 33 : 16), Qt::PreciseTimer);
|
||||
|
@ -139,12 +140,12 @@ void EBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *
|
|||
int bdWidth = borderImgs[bdImgIdx].img.height();
|
||||
int halfBdWidth = (bdWidth+1)/2;
|
||||
QBrush brush(borderImgs[bdImgIdx].img);
|
||||
QTransform transTop = QTransform::fromTranslate(halfBdWidth+bdOff, 0);
|
||||
QTransform transRight = QTransform::fromTranslate(mWidth - bdWidth, halfBdWidth*3-mWidth+bdOff);
|
||||
auto transTop = QTransform::fromTranslate(halfBdWidth+bdOff, 0);
|
||||
auto transRight = QTransform::fromTranslate(mWidth - bdWidth, halfBdWidth*3-mWidth+bdOff);
|
||||
transRight.rotate(90);
|
||||
QTransform transBottom = QTransform::fromTranslate(halfBdWidth*3-mHeight-bdOff, mHeight - bdWidth);
|
||||
auto transBottom = QTransform::fromTranslate(halfBdWidth*3-mHeight-bdOff, mHeight - bdWidth);
|
||||
transBottom.rotate(180);
|
||||
QTransform transLeft = QTransform::fromTranslate(0, halfBdWidth-bdOff);
|
||||
auto transLeft = QTransform::fromTranslate(0, halfBdWidth-bdOff);
|
||||
transLeft.rotate(270);
|
||||
|
||||
brush.setTransform(transTop);
|
||||
|
@ -185,6 +186,7 @@ void EBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *
|
|||
mSidePen.setColor(Qt::green);
|
||||
painter->setPen(mSidePen);
|
||||
painter->drawRect(0, 0, mWidth, mHeight);
|
||||
if(rotation()==0) {
|
||||
m_rLT = QRectF(-m_handleLen/2, -m_handleLen/2, m_handleLen, m_handleLen);//左上角
|
||||
m_rT = QRectF(mWidth/2 - m_handleLen/2, -m_handleLen/2, m_handleLen, m_handleLen);//上中
|
||||
m_rRT = QRectF(mWidth - m_handleLen/2, - m_handleLen/2, m_handleLen, m_handleLen);//右上角
|
||||
|
@ -193,8 +195,7 @@ void EBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *
|
|||
m_rLB = QRectF(-m_handleLen/2, mHeight - m_handleLen/2, m_handleLen, m_handleLen);
|
||||
m_rB = QRectF(mWidth/2 - m_handleLen/2, mHeight - m_handleLen/2, m_handleLen, m_handleLen);
|
||||
m_rRB = QRectF(mWidth - m_handleLen/2, mHeight - m_handleLen/2, m_handleLen, m_handleLen);
|
||||
static QPen handlePen = QPen(Qt::green);
|
||||
painter->setPen(handlePen);
|
||||
painter->setPen(Qt::green);
|
||||
painter->drawRect(m_rLT);
|
||||
painter->drawRect(m_rT);
|
||||
painter->drawRect(m_rRT);
|
||||
|
@ -203,6 +204,7 @@ void EBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *
|
|||
painter->drawRect(m_rLB);
|
||||
painter->drawRect(m_rB);
|
||||
painter->drawRect(m_rRB);
|
||||
}
|
||||
} else {
|
||||
mSidePen.setColor(Qt::darkGreen);
|
||||
painter->setPen(mSidePen);
|
||||
|
@ -265,10 +267,11 @@ void EBase::mouseMoveEvent(QGraphicsSceneMouseEvent *e){
|
|||
mLRSnap = mTBSnap = 0;
|
||||
for(auto ele : mOtherEles) ele->clearSnap();
|
||||
if(mFrmSec==Qt::TitleBarArea) {
|
||||
if(type()!=Web) {
|
||||
dstHor = qBound(0.0, dstHor, gProgItem->mWidth - mWidth);
|
||||
dstVer = qBound(0.0, dstVer, gProgItem->mHeight - mHeight);
|
||||
}
|
||||
if(rotation()==0) {
|
||||
// if(type()!=Web) {
|
||||
// dstHor = qBound(0.0, dstHor, gProgItem->mWidth - mWidth);
|
||||
// dstVer = qBound(0.0, dstVer, gProgItem->mHeight - mHeight);
|
||||
// }
|
||||
if(fabs(dstHor) < SnapSpace) {
|
||||
dstHor = 0;
|
||||
mLRSnap = 1;
|
||||
|
@ -346,18 +349,19 @@ void EBase::mouseMoveEvent(QGraphicsSceneMouseEvent *e){
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setPos(dstHor, dstVer);
|
||||
} else if(mFrmSec==Qt::BottomRightSection) {
|
||||
if(dstHor < m_handleLen) dstHor = m_handleLen;
|
||||
if(dstVer < m_handleLen) dstVer = m_handleLen;
|
||||
if(mType!=Web && gProgItem->mWidth>0 && gProgItem->mHeight>0) {
|
||||
dstHor = qMin(dstHor, gProgItem->mWidth - x());
|
||||
dstVer = qMin(dstVer, gProgItem->mHeight - y());
|
||||
}
|
||||
//if(mType!=Web && gProgItem->mWidth>0 && gProgItem->mHeight>0) {
|
||||
// dstHor = qMin(dstHor, gProgItem->mWidth - x());
|
||||
// dstVer = qMin(dstVer, gProgItem->mHeight - y());
|
||||
//}
|
||||
setSize(dstHor, dstVer);
|
||||
} else if(mFrmSec==Qt::RightSection) {
|
||||
if(dstHor < m_handleLen) dstHor = m_handleLen;
|
||||
if(mType!=Web && gProgItem->mWidth>0 && gProgItem->mHeight>0) dstHor = qMin(dstHor, gProgItem->mWidth - x());
|
||||
//if(mType!=Web && gProgItem->mWidth>0 && gProgItem->mHeight>0) dstHor = qMin(dstHor, gProgItem->mWidth - x());
|
||||
auto right = x() + dstHor;
|
||||
if(right < gProgItem->mWidth-8) for(EBase *ele : mOtherEles) {//左右
|
||||
if(fabs(right - ele->x()) < SnapSpace) {
|
||||
|
@ -379,7 +383,7 @@ void EBase::mouseMoveEvent(QGraphicsSceneMouseEvent *e){
|
|||
setSize(dstHor, mPressRel.y());
|
||||
} else if(mFrmSec==Qt::BottomSection) {
|
||||
if(dstVer < m_handleLen) dstVer = m_handleLen;
|
||||
if(mType!=Web && gProgItem->mWidth>0 && gProgItem->mHeight>0) dstVer = qMin(dstVer, gProgItem->mHeight - y());
|
||||
//if(mType!=Web && gProgItem->mWidth>0 && gProgItem->mHeight>0) dstVer = qMin(dstVer, gProgItem->mHeight - y());
|
||||
auto btm = y() + dstVer;
|
||||
if(btm < gProgItem->mHeight-8) for(EBase *ele : mOtherEles) {//上下
|
||||
auto eleBtm = ele->y() + ele->mHeight;
|
||||
|
@ -403,7 +407,7 @@ void EBase::mouseMoveEvent(QGraphicsSceneMouseEvent *e){
|
|||
QRectF geo(x(), y(), mWidth, mHeight);
|
||||
if(mFrmSec==Qt::LeftSection) {
|
||||
dstHor = qMin(dstHor, geo.right() - m_handleLen);
|
||||
if(mType!=Web && dstHor < 0) dstHor = 0;
|
||||
//if(mType!=Web && dstHor < 0) dstHor = 0;
|
||||
if(dstHor > 8) for(EBase *ele : mOtherEles) {//左右
|
||||
if(fabs(dstHor - ele->x()) < SnapSpace) {
|
||||
dstHor = ele->x();
|
||||
|
@ -425,7 +429,7 @@ void EBase::mouseMoveEvent(QGraphicsSceneMouseEvent *e){
|
|||
setX(dstHor);
|
||||
} else if(mFrmSec==Qt::TopSection) {
|
||||
dstVer = qMin(dstVer, geo.bottom() - m_handleLen);
|
||||
if(mType!=Web && dstVer < 0) dstVer = 0;
|
||||
//if(mType!=Web && dstVer < 0) dstVer = 0;
|
||||
if(dstVer > 8) for(EBase *ele : mOtherEles) {//上下
|
||||
if(fabs(dstVer - ele->y()) < SnapSpace) {
|
||||
dstVer = ele->y();
|
||||
|
@ -448,30 +452,30 @@ void EBase::mouseMoveEvent(QGraphicsSceneMouseEvent *e){
|
|||
} else if(mFrmSec==Qt::TopLeftSection) {
|
||||
dstHor = qMin(dstHor, geo.right() - m_handleLen);
|
||||
dstVer = qMin(dstVer, geo.bottom() - m_handleLen);
|
||||
if(mType!=Web) {
|
||||
if(dstHor < 0) dstHor = 0;
|
||||
if(dstVer < 0) dstVer = 0;
|
||||
}
|
||||
// if(mType!=Web) {
|
||||
// if(dstHor < 0) dstHor = 0;
|
||||
// if(dstVer < 0) dstVer = 0;
|
||||
// }
|
||||
geo.setLeft(dstHor);
|
||||
geo.setTop(dstVer);
|
||||
setPos(dstHor, dstVer);
|
||||
} else if(mFrmSec==Qt::TopRightSection) {
|
||||
dstHor = qMax(dstHor, geo.x() + m_handleLen);
|
||||
dstVer = qMin(dstVer, geo.bottom() - m_handleLen);
|
||||
if(mType!=Web) {
|
||||
if(dstHor > gProgItem->mWidth) dstHor = gProgItem->mWidth;
|
||||
if(dstVer < 0) dstVer = 0;
|
||||
}
|
||||
// if(mType!=Web) {
|
||||
// if(dstHor > gProgItem->mWidth) dstHor = gProgItem->mWidth;
|
||||
// if(dstVer < 0) dstVer = 0;
|
||||
// }
|
||||
geo.setRight(dstHor);
|
||||
geo.setTop(dstVer);
|
||||
setY(dstVer);
|
||||
} else if(mFrmSec==Qt::BottomLeftSection) {
|
||||
dstHor = qMin(dstHor, geo.right() - m_handleLen);
|
||||
dstVer = qMax(dstVer, geo.y() + m_handleLen);
|
||||
if(mType!=Web) {
|
||||
if(dstHor < 0) dstHor = 0;
|
||||
if(dstVer > gProgItem->mHeight) dstVer = gProgItem->mHeight;
|
||||
}
|
||||
// if(mType!=Web) {
|
||||
// if(dstHor < 0) dstHor = 0;
|
||||
// if(dstVer > gProgItem->mHeight) dstVer = gProgItem->mHeight;
|
||||
// }
|
||||
geo.setLeft(dstHor);
|
||||
geo.setBottom(dstVer);
|
||||
setX(dstHor);
|
||||
|
@ -488,6 +492,7 @@ void EBase::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
|||
}
|
||||
|
||||
void EBase::setFrmSec(const QPointF &pos) {
|
||||
if(rotation()==0) {
|
||||
if(m_rLT.contains(pos)) setFrmSecIfNeed(Qt::TopLeftSection, Qt::SizeFDiagCursor);
|
||||
else if(m_rT.contains(pos)) setFrmSecIfNeed(Qt::TopSection, Qt::SizeVerCursor);
|
||||
else if(m_rRT.contains(pos)) setFrmSecIfNeed(Qt::TopRightSection, Qt::SizeBDiagCursor);
|
||||
|
@ -498,6 +503,10 @@ void EBase::setFrmSec(const QPointF &pos) {
|
|||
else if(m_rRB.contains(pos)) setFrmSecIfNeed(Qt::BottomRightSection, Qt::SizeFDiagCursor);
|
||||
else if(pos.x()>=0 && pos.x()<=mWidth && pos.y()>=0 && pos.y()<=mHeight) setFrmSecIfNeed(Qt::TitleBarArea, Qt::SizeAllCursor);
|
||||
else setFrmSecIfNeed(Qt::NoSection, Qt::ArrowCursor);
|
||||
} else {
|
||||
if(pos.x()>=0 && pos.x()<=mWidth && pos.y()>=0 && pos.y()<=mHeight) setFrmSecIfNeed(Qt::TitleBarArea, Qt::SizeAllCursor);
|
||||
else setFrmSecIfNeed(Qt::NoSection, Qt::ArrowCursor);
|
||||
}
|
||||
}
|
||||
void EBase::setFrmSecIfNeed(Qt::WindowFrameSection frmSec, Qt::CursorShape cursor) {
|
||||
if(mFrmSec==frmSec) return;
|
||||
|
@ -564,16 +573,16 @@ void EBase::addBaseAttrWgt(QBoxLayout *vBox) {
|
|||
auto fdX = new QSpinBox;
|
||||
fdX->setRange(-99999, 999999);
|
||||
fdX->setValue(x());
|
||||
connect(fdX, &QSpinBox::valueChanged, this, [this, fdX](int value) {
|
||||
if(type()!=Web) {
|
||||
int max = gProgItem->mWidth - mWidth;
|
||||
if(value < 0 || value > max) {
|
||||
value = max;
|
||||
fdX->blockSignals(true);
|
||||
fdX->setValue(value);
|
||||
fdX->blockSignals(false);
|
||||
}
|
||||
}
|
||||
connect(fdX, &QSpinBox::valueChanged, this, [=](int value) {
|
||||
// if(type()!=Web) {
|
||||
// int max = gProgItem->mWidth - mWidth;
|
||||
// if(value < 0 || value > max) {
|
||||
// value = max;
|
||||
// fdX->blockSignals(true);
|
||||
// fdX->setValue(value);
|
||||
// fdX->blockSignals(false);
|
||||
// }
|
||||
// }
|
||||
setX(value);
|
||||
});
|
||||
hBox->addWidget(fdX);
|
||||
|
@ -584,16 +593,16 @@ void EBase::addBaseAttrWgt(QBoxLayout *vBox) {
|
|||
auto fdY = new QSpinBox;
|
||||
fdY->setRange(-99999, 999999);
|
||||
fdY->setValue(y());
|
||||
connect(fdY, &QSpinBox::valueChanged, this, [this, fdY](int value) {
|
||||
if(type()!=Web) {
|
||||
int max = gProgItem->mHeight - mHeight;
|
||||
if(value < 0 || value > max) {
|
||||
value = max;
|
||||
fdY->blockSignals(true);
|
||||
fdY->setValue(value);
|
||||
fdY->blockSignals(false);
|
||||
}
|
||||
}
|
||||
connect(fdY, &QSpinBox::valueChanged, this, [=](int value) {
|
||||
// if(type()!=Web) {
|
||||
// int max = gProgItem->mHeight - mHeight;
|
||||
// if(value < 0 || value > max) {
|
||||
// value = max;
|
||||
// fdY->blockSignals(true);
|
||||
// fdY->setValue(value);
|
||||
// fdY->blockSignals(false);
|
||||
// }
|
||||
// }
|
||||
setY(value);
|
||||
});
|
||||
hBox->addWidget(fdY);
|
||||
|
@ -606,16 +615,16 @@ void EBase::addBaseAttrWgt(QBoxLayout *vBox) {
|
|||
auto fdW = new QSpinBox;
|
||||
fdW->setRange(6, 999999);
|
||||
fdW->setValue(mWidth);
|
||||
connect(fdW, &QSpinBox::valueChanged, this, [this, fdW](int value) {
|
||||
if(type()!=Web) {
|
||||
int max = gProgItem->mWidth - x();
|
||||
if(value > max) {
|
||||
value = max;
|
||||
fdW->blockSignals(true);
|
||||
fdW->setValue(value);
|
||||
fdW->blockSignals(false);
|
||||
}
|
||||
}
|
||||
connect(fdW, &QSpinBox::valueChanged, this, [=](int value) {
|
||||
// if(type()!=Web) {
|
||||
// int max = gProgItem->mWidth - x();
|
||||
// if(value > max) {
|
||||
// value = max;
|
||||
// fdW->blockSignals(true);
|
||||
// fdW->setValue(value);
|
||||
// fdW->blockSignals(false);
|
||||
// }
|
||||
// }
|
||||
setSize(value, mHeight);
|
||||
});
|
||||
hBox->addWidget(fdW);
|
||||
|
@ -625,16 +634,16 @@ void EBase::addBaseAttrWgt(QBoxLayout *vBox) {
|
|||
auto fdH = new QSpinBox;
|
||||
fdH->setRange(6, 999999);
|
||||
fdH->setValue(mHeight);
|
||||
connect(fdH, &QSpinBox::valueChanged, this, [this, fdH](int value) {
|
||||
if(type()!=Web) {
|
||||
int max = gProgItem->mHeight - y();
|
||||
if(value > max) {
|
||||
value = max;
|
||||
fdH->blockSignals(true);
|
||||
fdH->setValue(value);
|
||||
fdH->blockSignals(false);
|
||||
}
|
||||
}
|
||||
connect(fdH, &QSpinBox::valueChanged, this, [=](int value) {
|
||||
// if(type()!=Web) {
|
||||
// int max = gProgItem->mHeight - y();
|
||||
// if(value > max) {
|
||||
// value = max;
|
||||
// fdH->blockSignals(true);
|
||||
// fdH->setValue(value);
|
||||
// fdH->blockSignals(false);
|
||||
// }
|
||||
// }
|
||||
setSize(mWidth, value);
|
||||
});
|
||||
hBox->addWidget(fdH);
|
||||
|
@ -663,13 +672,16 @@ void EBase::addBaseAttrWgt(QBoxLayout *vBox) {
|
|||
hBox->addStretch();
|
||||
hBox->addLabel(tr("Rotate")+": ");
|
||||
|
||||
auto fdRotate = new QSpinBox;
|
||||
fdRotate->setRange(-180, 360);
|
||||
fdRotate->setValue(_rotate);
|
||||
auto fdRotate = new QDoubleSpinBox;
|
||||
fdRotate->setDecimals(1);
|
||||
fdRotate->setSingleStep(15);
|
||||
fdRotate->setRange(-360, 360);
|
||||
fdRotate->setValue(rotation());
|
||||
fdRotate->setToolTip("Need Player 2.1.9");
|
||||
connect(fdRotate, &QSpinBox::valueChanged, this, [this](int value) {
|
||||
_rotate = value;
|
||||
//setRotation(value);
|
||||
connect(fdRotate, &QDoubleSpinBox::valueChanged, this, [=](double value) {
|
||||
if(value > 270) fdRotate->setValue(value-360);
|
||||
else if(value < -270) fdRotate->setValue(value+360);
|
||||
else setRotation(value);
|
||||
});
|
||||
hBox->addWidget(fdRotate);
|
||||
hBox->addSpacing(-spacing+2);
|
||||
|
@ -682,10 +694,9 @@ void EBase::addBaseAttrWgt(QBoxLayout *vBox) {
|
|||
fdOpacity->setDecimals(2);
|
||||
fdOpacity->setSingleStep(0.1);
|
||||
fdOpacity->setRange(0, 1);
|
||||
fdOpacity->setValue(_opacity);
|
||||
fdOpacity->setValue(opacity());
|
||||
fdOpacity->setToolTip("Need Player 2.1.9");
|
||||
connect(fdOpacity, (void(QDoubleSpinBox::*)(double))&QDoubleSpinBox::valueChanged, this, [this](double value) {
|
||||
_opacity = value;
|
||||
connect(fdOpacity, &QDoubleSpinBox::valueChanged, this, [=](double value) {
|
||||
setOpacity(value);
|
||||
});
|
||||
hBox->addWidget(fdOpacity);
|
||||
|
|
|
@ -18,7 +18,7 @@ public:
|
|||
};
|
||||
Q_ENUM(ElementType)
|
||||
|
||||
explicit EBase(EBase *multiWin = nullptr);
|
||||
explicit EBase(EBase *multiWin = 0);
|
||||
|
||||
void setBaseAttr(const JObj &);
|
||||
void addBaseAttr(JObj &) const;
|
||||
|
@ -35,6 +35,7 @@ public:
|
|||
prepareGeometryChange();
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
setTransformOriginPoint(mWidth/2, mHeight/2);
|
||||
emit sizeChanged();
|
||||
}
|
||||
void fitProgSize();
|
||||
|
@ -44,12 +45,11 @@ public:
|
|||
int mType = -1;
|
||||
EBase *mMultiWin = 0;
|
||||
qreal mWidth = 0, mHeight = 0;
|
||||
int _rotate = 0;
|
||||
QSpinBox *edDuration;
|
||||
int _startTime = 0, _duration = 10;
|
||||
QString mEntryEffect, mExitEffect;
|
||||
int mEntryDur = 1, mExitDur = 1;
|
||||
double _opacity = 1, _blink = 1;
|
||||
double _blink = 1;
|
||||
bool _hasBlink = false, _hasBreathe = false;
|
||||
signals:
|
||||
void sizeChanged();
|
||||
|
|
|
@ -4,23 +4,145 @@
|
|||
#include <QSpinBox>
|
||||
#include <QLineEdit>
|
||||
#include <QPainter>
|
||||
#include "xlsxcellrange.h"
|
||||
#include "xlsxchart.h"
|
||||
#include "xlsxchartsheet.h"
|
||||
#include "xlsxdocument.h"
|
||||
#include "xlsxrichstring.h"
|
||||
#include "xlsxworkbook.h"
|
||||
#include "xlsxworksheet.h"
|
||||
|
||||
ETable::ETable(EBase *multiWin) : EBase(multiWin) {
|
||||
mType = EBase::Table;
|
||||
dlg.setWindowFlag(Qt::WindowContextHelpButtonHint, 0);
|
||||
dlg.resize(600, 600);
|
||||
dlg.setWindowTitle(tr("Table Editor"));
|
||||
auto vBox = new VBox(&dlg);
|
||||
vBox->setContentsMargins(6, 0, 6, 0);
|
||||
|
||||
auto hBox = new HBox(vBox);
|
||||
hBox = new HBox(vBox);
|
||||
table = new TableWidget(8, 3);
|
||||
auto pal = table->palette();
|
||||
pal.setBrush(QPalette::Active, QPalette::WindowText, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::WindowText, QBrush({157,157,157,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::WindowText, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Button, QBrush({60,60,60,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Button, QBrush({60,60,60,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Button, QBrush({60,60,60,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Light, QBrush({120,120,120,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Light, QBrush({120,120,120,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Light, QBrush({120,120,120,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Midlight, QBrush({90,90,90,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Midlight, QBrush({90,90,90,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Midlight, QBrush({90,90,90,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Dark, QBrush({30,30,30,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Dark, QBrush({30,30,30,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Dark, QBrush({30,30,30,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Mid, QBrush({40,40,40,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Mid, QBrush({40,40,40,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Mid, QBrush({40,40,40,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Text, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Text, QBrush({157,157,157,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Text, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::BrightText, QBrush({95,255,165,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::BrightText, QBrush({95,255,165,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::BrightText, QBrush({95,255,165,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::ButtonText, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::ButtonText, QBrush({157,157,157,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::ButtonText, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Base, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Base, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Base, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Window, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Window, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Window, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Shadow, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Shadow, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Shadow, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Highlight, QBrush({0,204,106,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Highlight, QBrush({0,204,106,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Highlight, QBrush({30,30,30,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::HighlightedText, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::HighlightedText, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::HighlightedText, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::Link, QBrush({0,204,106,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::Link, QBrush({48,140,198,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Link, QBrush({0,204,106,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::LinkVisited, QBrush({0,63,19,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::LinkVisited, QBrush({255,0,255,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::LinkVisited, QBrush({0,63,19,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::AlternateBase, QBrush({0,63,19,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::AlternateBase, QBrush({52,52,52,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::AlternateBase, QBrush({0,63,19,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::NoRole, QBrush({0,0,0,255}, Qt::NoBrush));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::NoRole, QBrush({0,0,0,255}, Qt::NoBrush));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::NoRole, QBrush({0,0,0,255}, Qt::NoBrush));
|
||||
pal.setBrush(QPalette::Active, QPalette::ToolTipBase, QBrush({60,60,60,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::ToolTipBase, QBrush({255,255,220,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::ToolTipBase, QBrush({60,60,60,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::ToolTipText, QBrush({212,212,212,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::ToolTipText, QBrush({0,0,0,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::ToolTipText, QBrush({212,212,212,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::PlaceholderText, QBrush({255,255,255,128}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::PlaceholderText, QBrush({255,255,255,128}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Inactive, QPalette::PlaceholderText, QBrush({255,255,255,128}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Active, QPalette::NColorRoles, QBrush({157,157,157,255}, Qt::SolidPattern));
|
||||
pal.setBrush(QPalette::Disabled, QPalette::NColorRoles, QBrush({255,255,255,255}, Qt::SolidPattern));
|
||||
|
||||
pal.setBrush(QPalette::Inactive, QPalette::Highlight, pal.brush(QPalette::Active, QPalette::Highlight));
|
||||
table->setPalette(pal);
|
||||
auto ft = table->font();
|
||||
ft.setStyleStrategy(QFont::NoAntialias);
|
||||
table->setFont(ft);
|
||||
table->setShowGrid(false);
|
||||
table->setStyleSheet("QTableView::item { border: 1px solid red;}");
|
||||
vBox->addWidget(table);
|
||||
|
||||
read();
|
||||
}
|
||||
ETable::ETable(const JObj &json, EBase *multiWin) : EBase(multiWin) {
|
||||
mType = EBase::Table;
|
||||
setBaseAttr(json);
|
||||
url = json["url"].toString();
|
||||
read();
|
||||
}
|
||||
int ETable::read() {
|
||||
QXlsx::Document xlsxDoc("d:/aaa.xlsx");
|
||||
if(! xlsxDoc.isLoadPackage()) {
|
||||
qCritical() << "Failed to load xlsx";
|
||||
return -1;
|
||||
}
|
||||
auto currentSheet = xlsxDoc.currentWorksheet();
|
||||
if(currentSheet == 0) {
|
||||
qCritical() << "Failed to load Worksheet";
|
||||
return -1;
|
||||
}
|
||||
int maxRow = -1, maxCol = -1;
|
||||
auto cells = currentSheet->getFullCells(&maxRow, &maxCol);
|
||||
for(auto &cell : cells) {
|
||||
auto value = cell.cell->value();
|
||||
auto fmt = cell.cell->format();
|
||||
fmt.font();
|
||||
qDebug()<<cell.row<<cell.col<<cell.cell->cellType()<<fmt.font()<<fmt.fontColor()<<fmt.patternBackgroundColor()<<value;
|
||||
}
|
||||
}
|
||||
|
||||
void ETable::paint(QPainter *painter, const QStyleOptionGraphicsItem *a, QWidget *b) {
|
||||
auto inner = innerRect();
|
||||
painter->setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);
|
||||
//painter->drawImage(QRectF(inner.width()/2, inner.height()/2, maskW, maskH), holder());
|
||||
painter->drawPixmap(inner.left(), inner.top(), img);
|
||||
EBase::paint(painter, a, b);
|
||||
}
|
||||
|
||||
void ETable::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
|
||||
dlg.exec();
|
||||
img = table->grab();
|
||||
auto twidth = table->width();
|
||||
if(twidth != img.width()) {
|
||||
img = img.scaledToWidth(twidth, Qt::SmoothTransformation);
|
||||
qDebug()<<"scaledToWidth"<<twidth;
|
||||
}
|
||||
}
|
||||
QWidget* ETable::attrWgt() {
|
||||
auto wgtAttr = new QWidget;
|
||||
auto vBox = new VBox(wgtAttr);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define ETABLE_H
|
||||
|
||||
#include "ebase.h"
|
||||
#include "gutil/qgui.h"
|
||||
#include <QDialog>
|
||||
|
||||
class ETable : public EBase {
|
||||
Q_OBJECT
|
||||
|
@ -9,12 +11,17 @@ public:
|
|||
explicit ETable(EBase *multiWin = 0);
|
||||
explicit ETable(const JObj &json, EBase *multiWin = 0);
|
||||
|
||||
int read();
|
||||
int type() const override {return EBase::Table;}
|
||||
void paint(QPainter*, const QStyleOptionGraphicsItem *, QWidget *) override;
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
QWidget* attrWgt() override;
|
||||
bool save(const QString &) override {return true;};
|
||||
JObj attrJson() const override;
|
||||
|
||||
QDialog dlg;
|
||||
TableWidget *table;
|
||||
QPixmap img;
|
||||
QString url;
|
||||
int zoom = 100, refresh = 0, _x = 0, _y = 0, scaleX = 100, scaleY = 100;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user