From e0873308a615c7e8f78fe653fd3bb2ecf4739501 Mon Sep 17 00:00:00 2001
From: wumu <mayi@mayi.com>
Date: 星期三, 14 六月 2023 23:08:24 +0800
Subject: [PATCH] qxlsm

---
 internal_system_v1/QXlsx/header/xlsxconditionalformatting.h          |  120 
 internal_system_v1/QXlsx/header/xlsxcellreference.h                  |   47 
 internal_system_v1/QXlsx/header/xlsxworksheet_p.h                    |  252 
 internal_system_v1/QXlsx/source/xlsxcellreference.cpp                |  154 
 internal_system_v1/QXlsx/header/xlsxdatetype.h                       |   48 
 internal_system_v1/clientmainwindow.cpp                              |   18 
 internal_system_v1/punish.cpp                                        |   10 
 internal_system_v1/QXlsx/source/xlsxdrawing.cpp                      |   84 
 internal_system_v1/QXlsx/source/xlsxdocpropscore.cpp                 |  176 
 internal_system_v1/QXlsx/header/xlsxsimpleooxmlfile_p.h              |   60 
 internal_system_v1/QXlsx/source/xlsxrichstring.cpp                   |  329 
 internal_system_v1/QXlsx/header/xlsxcell_p.h                         |   41 
 internal_system_v1/caseclue.cpp                                      |    1 
 internal_system_v1/QXlsx/source/xlsxcontenttypes.cpp                 |  184 
 internal_system_v1/QXlsx/source/xlsxstyles.cpp                       | 1409 +++
 internal_system_v1/QXlsx/header/xlsxcellrange.h                      |   73 
 internal_system_v1/QXlsx/source/xlsxutility.cpp                      |  291 
 internal_system_v1/QXlsx/source/xlsxcellrange.cpp                    |  127 
 internal_system_v1/QXlsx/header/xlsxchart_p.h                        |  148 
 internal_system_v1/QXlsx/header/xlsxformat_p.h                       |  130 
 internal_system_v1/QXlsx/header/xlsxrichstring_p.h                   |   60 
 internal_system_v1/punish.ui                                         |  126 
 internal_system_v1/QXlsx/header/xlsxrelationships_p.h                |   89 
 internal_system_v1/QXlsx/source/xlsxworkbook.cpp                     |  740 +
 internal_system_v1/QXlsx/cmake/modules/CPackConfig.cmake             |   21 
 internal_system_v1/QXlsx/header/xlsxcellformula.h                    |   55 
 internal_system_v1/QXlsx/source/xlsxdatavalidation.cpp               |  537 +
 internal_system_v1/QXlsx/source/xlsxdocument.cpp                     | 1454 +++
 internal_system_v1/QXlsx/source/xlsxchartsheet.cpp                   |  142 
 internal_system_v1/QXlsx/cmake/modules/qxlsx-config-version.cmake.in |   15 
 internal_system_v1/QXlsx/header/xlsxdatavalidation_p.h               |   37 
 internal_system_v1/QXlsx/cmake/modules/qxlsx-config.cmake.in         |   14 
 internal_system_v1/QXlsx/header/xlsxdatavalidation.h                 |  105 
 internal_system_v1/internal_system_v1.pro                            |    2 
 internal_system_v1/QXlsx/header/xlsxdrawing_p.h                      |   38 
 internal_system_v1/QXlsx/header/xlsxdrawinganchor_p.h                |  169 
 internal_system_v1/auditworkload.ui                                  |  103 
 internal_system_v1/QXlsx/header/xlsxdocpropscore_p.h                 |   34 
 internal_system_v1/QXlsx/source/xlsxzipreader.cpp                    |   50 
 internal_system_v1/QXlsx/header/xlsxchart.h                          |   58 
 internal_system_v1/QXlsx/source/xlsxnumformatparser.cpp              |   74 
 internal_system_v1/QXlsx/source/xlsxzipwriter.cpp                    |   48 
 internal_system_v1/QXlsx/header/xlsxutility_p.h                      |   42 
 internal_system_v1/QXlsx/QXlsx.pri                                   |  204 
 internal_system_v1/QXlsx/header/xlsxcelllocation.h                   |   33 
 internal_system_v1/QXlsx/QXlsx.pro                                   |   32 
 internal_system_v1/QXlsx/header/xlsxtheme_p.h                        |   29 
 internal_system_v1/QXlsx/source/xlsxdatetype.cpp                     |   85 
 internal_system_v1/QXlsx/header/xlsxzipwriter_p.h                    |   34 
 internal_system_v1/QXlsx/header/xlsxdocpropsapp_p.h                  |   40 
 internal_system_v1/QXlsx/source/xlsxtheme.cpp                        |  216 
 internal_system_v1/QXlsx/source/xlsxrelationships.cpp                |  169 
 internal_system_v1/QXlsx/source/xlsxworksheet.cpp                    | 3083 +++++++
 internal_system_v1/QXlsx/header/xlsxzipreader_p.h                    |   37 
 internal_system_v1/QXlsx/header/xlsxstyles_p.h                       |  143 
 internal_system_v1/QXlsx/header/xlsxglobal.h                         |   33 
 internal_system_v1/QXlsx/header/xlsxworkbook.h                       |   95 
 internal_system_v1/QXlsx/source/xlsxformat.cpp                       | 1437 +++
 internal_system_v1/QXlsx/source/xlsxconditionalformatting.cpp        |  751 +
 internal_system_v1/QXlsx/source/xlsxsharedstrings.cpp                |  382 
 internal_system_v1/clientmainwindow.ui                               |   22 
 internal_system_v1/QXlsx/source/xlsxabstractsheet.cpp                |  186 
 internal_system_v1/caseclue.ui                                       |  101 
 internal_system_v1/QXlsx/source/xlsxcolor.cpp                        |  196 
 internal_system_v1/problemnotmoney.ui                                |  151 
 internal_system_v1/QXlsx/source/xlsxcellformula.cpp                  |  453 +
 internal_system_v1/clientmainwindow.h                                |    4 
 internal_system_v1/QXlsx/source/xlsxchart.cpp                        | 2335 +++++
 internal_system_v1/QXlsx/header/xlsxnumformatparser_p.h              |   51 
 internal_system_v1/QXlsx/source/xlsxsimpleooxmlfile.cpp              |   37 
 internal_system_v1/QXlsx/header/xlsxformat.h                         |  262 
 internal_system_v1/QXlsx/source/xlsxabstractooxmlfile.cpp            |   97 
 internal_system_v1/QXlsx/source/xlsxcelllocation.cpp                 |   23 
 internal_system_v1/QXlsx/source/xlsxdocpropsapp.cpp                  |  138 
 internal_system_v1/QXlsx/header/xlsxcell.h                           |   82 
 internal_system_v1/QXlsx/header/xlsxdocument.h                       |  143 
 internal_system_v1/QXlsx/header/xlsxabstractsheet.h                  |   49 
 internal_system_v1/problemnotmoney.cpp                               |   10 
 internal_system_v1/punish.h                                          |    3 
 internal_system_v1/QXlsx/header/xlsxdocument_p.h                     |   41 
 internal_system_v1/QXlsx/header/xlsxabstractooxmlfile.h              |   47 
 internal_system_v1/auditproject.ui                                   |  478 
 internal_system_v1/QXlsx/header/xlsxchartsheet_p.h                   |   25 
 internal_system_v1/QXlsx/header/xlsxrichstring.h                     |   89 
 internal_system_v1/QXlsx/header/xlsxconditionalformatting_p.h        |   99 
 internal_system_v1/QXlsx/header/xlsxcolor_p.h                        |   59 
 internal_system_v1/QXlsx/header/xlsxsharedstrings_p.h                |   98 
 internal_system_v1/QXlsx/header/xlsxabstractsheet_p.h                |   36 
 internal_system_v1/QXlsx/source/xlsxdrawinganchor.cpp                | 1203 +++
 internal_system_v1/QXlsx/header/xlsxworkbook_p.h                     |   74 
 internal_system_v1/problemcount.ui                                   |  354 
 internal_system_v1/QXlsx/source/xlsxcell.cpp                         |  364 
 internal_system_v1/QXlsx/header/xlsxabstractooxmlfile_p.h            |   31 
 internal_system_v1/QXlsx/header/xlsxchartsheet.h                     |   38 
 internal_system_v1/QXlsx/CMakeLists.txt                              |  220 
 internal_system_v1/QXlsx/source/xlsxmediafile.cpp                    |   78 
 internal_system_v1/QXlsx/header/xlsxmediafile_p.h                    |   46 
 internal_system_v1/problemnotmoney.h                                 |    3 
 internal_system_v1/QXlsx/header/xlsxworksheet.h                      |  164 
 internal_system_v1/QXlsx/header/xlsxcellformula_p.h                  |   31 
 internal_system_v1/problemmoney.ui                                   |  514 
 internal_system_v1/problemrectification.ui                           |  354 
 internal_system_v1/QXlsx/header/xlsxcontenttypes_p.h                 |   55 
 103 files changed, 22,393 insertions(+), 969 deletions(-)

diff --git a/internal_system_v1/QXlsx/CMakeLists.txt b/internal_system_v1/QXlsx/CMakeLists.txt
new file mode 100644
index 0000000..57327cf
--- /dev/null
+++ b/internal_system_v1/QXlsx/CMakeLists.txt
@@ -0,0 +1,220 @@
+# CMakeLists.txt for QXlsx Library
+
+cmake_minimum_required(VERSION 3.16)
+
+project(QXlsx
+    VERSION 1.4.4
+    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)
+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(NOT DEFINED ${QXLSX_PARENTPATH})
+
+if(NOT DEFINED ${QXLSX_HEADERPATH})
+	set(QXLSX_HEADERPATH ${CMAKE_CURRENT_SOURCE_DIR}/../QXlsx/header/)
+endif(NOT DEFINED ${QXLSX_HEADERPATH})
+
+if(NOT DEFINED ${QXLSX_SOURCEPATH})
+	set(QXLSX_SOURCEPATH ${CMAKE_CURRENT_SOURCE_DIR}/../QXlsx/source/)
+endif(NOT DEFINED ${QXLSX_SOURCEPATH})
+
+message("Current Path of QXlsx")
+message(${QXLSX_PARENTPATH})
+message(${QXLSX_HEADERPATH})
+message(${QXLSX_SOURCEPATH})
+
+# 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=0x060200
+)
+
+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 0.${PROJECT_VERSION}
+    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)
diff --git a/internal_system_v1/QXlsx/QXlsx.pri b/internal_system_v1/QXlsx/QXlsx.pri
new file mode 100644
index 0000000..8e2ea59
--- /dev/null
+++ b/internal_system_v1/QXlsx/QXlsx.pri
@@ -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 {
+	}		
+}
+
diff --git a/internal_system_v1/QXlsx/QXlsx.pro b/internal_system_v1/QXlsx/QXlsx.pro
new file mode 100644
index 0000000..c4946b8
--- /dev/null
+++ b/internal_system_v1/QXlsx/QXlsx.pro
@@ -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)
+
+
diff --git a/internal_system_v1/QXlsx/cmake/modules/CPackConfig.cmake b/internal_system_v1/QXlsx/cmake/modules/CPackConfig.cmake
new file mode 100644
index 0000000..07dd1ab
--- /dev/null
+++ b/internal_system_v1/QXlsx/cmake/modules/CPackConfig.cmake
@@ -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)
diff --git a/internal_system_v1/QXlsx/cmake/modules/qxlsx-config-version.cmake.in b/internal_system_v1/QXlsx/cmake/modules/qxlsx-config-version.cmake.in
new file mode 100644
index 0000000..68cbf8f
--- /dev/null
+++ b/internal_system_v1/QXlsx/cmake/modules/qxlsx-config-version.cmake.in
@@ -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)
diff --git a/internal_system_v1/QXlsx/cmake/modules/qxlsx-config.cmake.in b/internal_system_v1/QXlsx/cmake/modules/qxlsx-config.cmake.in
new file mode 100644
index 0000000..d72276b
--- /dev/null
+++ b/internal_system_v1/QXlsx/cmake/modules/qxlsx-config.cmake.in
@@ -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")
diff --git a/internal_system_v1/QXlsx/header/xlsxabstractooxmlfile.h b/internal_system_v1/QXlsx/header/xlsxabstractooxmlfile.h
new file mode 100644
index 0000000..8355b0b
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxabstractooxmlfile.h
@@ -0,0 +1,47 @@
+// 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
diff --git a/internal_system_v1/QXlsx/header/xlsxabstractooxmlfile_p.h b/internal_system_v1/QXlsx/header/xlsxabstractooxmlfile_p.h
new file mode 100644
index 0000000..30fea98
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxabstractooxmlfile_p.h
@@ -0,0 +1,31 @@
+// xlsxabstractooxmlfile_p.h
+
+#ifndef XLSXOOXMLFILE_P_H
+#define XLSXOOXMLFILE_P_H
+
+#include "xlsxglobal.h"
+
+#include "xlsxabstractooxmlfile.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
diff --git a/internal_system_v1/QXlsx/header/xlsxabstractsheet.h b/internal_system_v1/QXlsx/header/xlsxabstractsheet.h
new file mode 100644
index 0000000..8104740
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxabstractsheet.h
@@ -0,0 +1,49 @@
+// xlsxabstractsheet.h
+
+#ifndef XLSXABSTRACTSHEET_H
+#define XLSXABSTRACTSHEET_H
+
+#include "xlsxglobal.h"
+#include "xlsxabstractooxmlfile.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
diff --git a/internal_system_v1/QXlsx/header/xlsxabstractsheet_p.h b/internal_system_v1/QXlsx/header/xlsxabstractsheet_p.h
new file mode 100644
index 0000000..b95a058
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxabstractsheet_p.h
@@ -0,0 +1,36 @@
+// xlsxabstractsheet_p/h
+
+#ifndef XLSXABSTRACTSHEET_P_H
+#define XLSXABSTRACTSHEET_P_H
+
+#include <QString>
+
+#include <memory>
+
+#include "xlsxglobal.h"
+
+#include "xlsxabstractsheet.h"
+#include "xlsxabstractooxmlfile_p.h"
+#include "xlsxdrawing_p.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxcell.h b/internal_system_v1/QXlsx/header/xlsxcell.h
new file mode 100644
index 0000000..619d41f
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxcell.h
@@ -0,0 +1,82 @@
+锘�// xlsxcell.h
+
+#ifndef QXLSX_XLSXCELL_H
+#define QXLSX_XLSXCELL_H
+
+#include <cstdio>
+
+#include <QtGlobal>
+#include <QObject>
+#include <QString>
+#include <QVariant>
+#include <QDate>
+#include <QDateTime>
+#include <QTime>
+
+#include "xlsxglobal.h"
+#include "xlsxformat.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxcell_p.h b/internal_system_v1/QXlsx/header/xlsxcell_p.h
new file mode 100644
index 0000000..0abcc42
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxcell_p.h
@@ -0,0 +1,41 @@
+// xlsxcell_p.h
+
+#ifndef XLSXCELL_P_H
+#define XLSXCELL_P_H
+
+#include <QtGlobal>
+#include <QObject>
+#include <QList>
+
+#include "xlsxglobal.h"
+#include "xlsxcell.h"
+#include "xlsxcellrange.h"
+#include "xlsxrichstring.h"
+#include "xlsxcellformula.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxcellformula.h b/internal_system_v1/QXlsx/header/xlsxcellformula.h
new file mode 100644
index 0000000..f0f4de4
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxcellformula.h
@@ -0,0 +1,55 @@
+// 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
diff --git a/internal_system_v1/QXlsx/header/xlsxcellformula_p.h b/internal_system_v1/QXlsx/header/xlsxcellformula_p.h
new file mode 100644
index 0000000..4390089
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxcellformula_p.h
@@ -0,0 +1,31 @@
+// xlsxcellformula_p.h
+
+#ifndef XLSXCELLFORMULA_P_H
+#define XLSXCELLFORMULA_P_H
+
+#include "xlsxglobal.h"
+#include "xlsxcellformula.h"
+#include "xlsxcellrange.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
diff --git a/internal_system_v1/QXlsx/header/xlsxcelllocation.h b/internal_system_v1/QXlsx/header/xlsxcelllocation.h
new file mode 100644
index 0000000..ccb5cdb
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxcelllocation.h
@@ -0,0 +1,33 @@
+// xlsxcelllocation.h
+
+#ifndef CELL_LOCATION_H
+#define CELL_LOCATION_H
+
+#include <QtGlobal>
+#include <QObject>
+#include <QString>
+#include <QVector>
+#include <QList>
+#include <QMetaType>
+
+#include <memory>
+
+#include "xlsxglobal.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxcellrange.h b/internal_system_v1/QXlsx/header/xlsxcellrange.h
new file mode 100644
index 0000000..719317c
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxcellrange.h
@@ -0,0 +1,73 @@
+// xlsxcellrange.h
+
+#ifndef QXLSX_XLSXCELLRANGE_H
+#define QXLSX_XLSXCELLRANGE_H
+
+#include <QtGlobal>
+#include <QObject>
+
+#include "xlsxglobal.h"
+#include "xlsxcellreference.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxcellreference.h b/internal_system_v1/QXlsx/header/xlsxcellreference.h
new file mode 100644
index 0000000..c20abdc
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxcellreference.h
@@ -0,0 +1,47 @@
+// xlsxcellreference.h
+
+#ifndef QXLSX_XLSXCELLREFERENCE_H
+#define QXLSX_XLSXCELLREFERENCE_H
+
+#include <QtGlobal>
+
+#include "xlsxglobal.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+class QXLSX_EXPORT CellReference
+{
+public:
+    CellReference();
+    CellReference(int row, int 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;
+    static CellReference fromString(const QString &cell);
+    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;
+    }
+private:
+    void init(const QString &cell);
+    int _row, _column;
+};
+
+QT_END_NAMESPACE_XLSX
+
+Q_DECLARE_TYPEINFO(QXlsx::CellReference, Q_MOVABLE_TYPE);
+
+#endif // QXLSX_XLSXCELLREFERENCE_H
diff --git a/internal_system_v1/QXlsx/header/xlsxchart.h b/internal_system_v1/QXlsx/header/xlsxchart.h
new file mode 100644
index 0000000..b724e79
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxchart.h
@@ -0,0 +1,58 @@
+// xlsxchart.h
+
+#ifndef QXLSX_CHART_H
+#define QXLSX_CHART_H
+
+#include <QtGlobal>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+#include "xlsxabstractooxmlfile.h"
+
+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 = NULL, 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
diff --git a/internal_system_v1/QXlsx/header/xlsxchart_p.h b/internal_system_v1/QXlsx/header/xlsxchart_p.h
new file mode 100644
index 0000000..1d5de8c
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxchart_p.h
@@ -0,0 +1,148 @@
+// xlsxchart_p.h
+
+#ifndef QXLSX_CHART_P_H
+#define QXLSX_CHART_P_H
+
+#include <QObject>
+#include <QString>
+#include <QVector>
+#include <QMap>
+#include <QList>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+#include <memory>
+
+#include "xlsxabstractooxmlfile_p.h"
+#include "xlsxchart.h"
+
+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 readed file
+};
+
+QT_END_NAMESPACE_XLSX
+
+#endif // QXLSX_CHART_P_H
diff --git a/internal_system_v1/QXlsx/header/xlsxchartsheet.h b/internal_system_v1/QXlsx/header/xlsxchartsheet.h
new file mode 100644
index 0000000..e654af1
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxchartsheet.h
@@ -0,0 +1,38 @@
+// xlsxchartsheet.h
+
+#ifndef XLSXCHARTSHEET_H
+#define XLSXCHARTSHEET_H
+
+#include <QtGlobal>
+#include <QStringList>
+
+#include "xlsxabstractsheet.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxchartsheet_p.h b/internal_system_v1/QXlsx/header/xlsxchartsheet_p.h
new file mode 100644
index 0000000..21ade91
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxchartsheet_p.h
@@ -0,0 +1,25 @@
+// xlsxchartsheet_p.h
+
+#ifndef XLSXCHARTSHEET_P_H
+#define XLSXCHARTSHEET_P_H
+
+#include <QtGlobal>
+
+#include "xlsxglobal.h"
+#include "xlsxchartsheet.h"
+#include "xlsxabstractsheet_p.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
diff --git a/internal_system_v1/QXlsx/header/xlsxcolor_p.h b/internal_system_v1/QXlsx/header/xlsxcolor_p.h
new file mode 100644
index 0000000..4fafacf
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxcolor_p.h
@@ -0,0 +1,59 @@
+// xlsxcolor_p.h
+
+#ifndef QXLSX_XLSXCOLOR_P_H
+#define QXLSX_XLSXCOLOR_P_H
+
+#include <QtGlobal>
+#include <QVariant>
+#include <QColor>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+
+#include "xlsxglobal.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxconditionalformatting.h b/internal_system_v1/QXlsx/header/xlsxconditionalformatting.h
new file mode 100644
index 0000000..117f74a
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxconditionalformatting.h
@@ -0,0 +1,120 @@
+// xlsxconditionalformatting.h
+
+#ifndef QXLSX_XLSXCONDITIONALFORMATTING_H
+#define QXLSX_XLSXCONDITIONALFORMATTING_H
+
+#include <QtGlobal>
+#include <QString>
+#include <QList>
+#include <QColor>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+#include <QSharedDataPointer>
+
+#include "xlsxglobal.h"
+#include "xlsxcellrange.h"
+#include "xlsxcellreference.h"
+
+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 = NULL);
+
+    QSharedDataPointer<ConditionalFormattingPrivate> d;
+};
+
+QT_END_NAMESPACE_XLSX
+
+#endif // QXLSX_XLSXCONDITIONALFORMATTING_H
diff --git a/internal_system_v1/QXlsx/header/xlsxconditionalformatting_p.h b/internal_system_v1/QXlsx/header/xlsxconditionalformatting_p.h
new file mode 100644
index 0000000..455af59
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxconditionalformatting_p.h
@@ -0,0 +1,99 @@
+// xlsxconditionalformatting_p.h
+
+#ifndef XLSXCONDITIONALFORMATTING_P_H
+#define XLSXCONDITIONALFORMATTING_P_H
+
+#include <QSharedData>
+#include <QMap>
+
+#include <memory>
+
+#include "xlsxconditionalformatting.h"
+#include "xlsxformat.h"
+#include "xlsxcolor_p.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxcontenttypes_p.h b/internal_system_v1/QXlsx/header/xlsxcontenttypes_p.h
new file mode 100644
index 0000000..43c73f0
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxcontenttypes_p.h
@@ -0,0 +1,55 @@
+// xlsxcontenttypes_p.h
+
+#ifndef XLSXCONTENTTYPES_H
+#define XLSXCONTENTTYPES_H
+
+#include <QtGlobal>
+#include <QString>
+#include <QStringList>
+#include <QMap>
+#include <QIODevice>
+
+#include "xlsxabstractooxmlfile.h"
+
+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 funcation 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
diff --git a/internal_system_v1/QXlsx/header/xlsxdatavalidation.h b/internal_system_v1/QXlsx/header/xlsxdatavalidation.h
new file mode 100644
index 0000000..ad8a1d6
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxdatavalidation.h
@@ -0,0 +1,105 @@
+// xlsxvalidation.h
+
+#ifndef QXLSX_XLSXDATAVALIDATION_H
+#define QXLSX_XLSXDATAVALIDATION_H
+
+#include <QtGlobal>
+#include <QSharedDataPointer>
+#include <QString>
+#include <QList>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+#include "xlsxglobal.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxdatavalidation_p.h b/internal_system_v1/QXlsx/header/xlsxdatavalidation_p.h
new file mode 100644
index 0000000..727a182
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxdatavalidation_p.h
@@ -0,0 +1,37 @@
+// xlsxdatavalidation_p.h
+
+#ifndef XLSXDATAVALIDATION_P_H
+#define XLSXDATAVALIDATION_P_H
+
+#include <QtGlobal>
+#include <QSharedData>
+
+#include "xlsxdatavalidation.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxdatetype.h b/internal_system_v1/QXlsx/header/xlsxdatetype.h
new file mode 100644
index 0000000..366d99a
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxdatetype.h
@@ -0,0 +1,48 @@
+// xlsxdatetype.h
+
+#ifndef QXLSX_XLSXDATETYPE_H
+#define QXLSX_XLSXDATETYPE_H
+
+#include <QtGlobal>
+#include <QObject>
+#include <QString>
+#include <QStringList>
+#include <QDateTime>
+#include <QDate>
+#include <QTime>
+
+#include "xlsxglobal.h"
+
+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 
diff --git a/internal_system_v1/QXlsx/header/xlsxdocpropsapp_p.h b/internal_system_v1/QXlsx/header/xlsxdocpropsapp_p.h
new file mode 100644
index 0000000..32b95fa
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxdocpropsapp_p.h
@@ -0,0 +1,40 @@
+// xlsxdocpropsapp_p.h
+
+#ifndef XLSXDOCPROPSAPP_H
+#define XLSXDOCPROPSAPP_H
+
+#include <QList>
+#include <QStringList>
+#include <QMap>
+
+#include "xlsxglobal.h"
+#include "xlsxabstractooxmlfile.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxdocpropscore_p.h b/internal_system_v1/QXlsx/header/xlsxdocpropscore_p.h
new file mode 100644
index 0000000..3aaace6
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxdocpropscore_p.h
@@ -0,0 +1,34 @@
+// xlsxdocpropscore_p.h
+
+#ifndef XLSXDOCPROPSCORE_H
+#define XLSXDOCPROPSCORE_H
+
+#include "xlsxglobal.h"
+#include "xlsxabstractooxmlfile.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
diff --git a/internal_system_v1/QXlsx/header/xlsxdocument.h b/internal_system_v1/QXlsx/header/xlsxdocument.h
new file mode 100644
index 0000000..5d3455f
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxdocument.h
@@ -0,0 +1,143 @@
+// xlsxdocument.h
+
+#ifndef QXLSX_XLSXDOCUMENT_H
+#define QXLSX_XLSXDOCUMENT_H
+
+#include <QtGlobal>
+#include <QObject>
+#include <QVariant>
+#include <QIODevice>
+#include <QImage>
+
+#include "xlsxglobal.h"
+#include "xlsxformat.h"
+#include "xlsxworksheet.h"
+
+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);
+
+	Cell *cellAt(const CellReference &cell) const;
+	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;
+
+	// 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(void);
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxdocument_p.h b/internal_system_v1/QXlsx/header/xlsxdocument_p.h
new file mode 100644
index 0000000..b15bdfa
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxdocument_p.h
@@ -0,0 +1,41 @@
+// xlsxdocument_p.h
+
+#ifndef XLSXDOCUMENT_P_H
+#define XLSXDOCUMENT_P_H
+
+#include <QtGlobal>
+#include <QMap>
+
+#include "xlsxglobal.h"
+#include "xlsxdocument.h"
+#include "xlsxworkbook.h"
+#include "xlsxcontenttypes_p.h"
+
+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;
+
+	// 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
+    QSharedPointer<Workbook> workbook;
+    std::shared_ptr<ContentTypes> contentTypes;
+	bool isLoad; 
+};
+
+QT_END_NAMESPACE_XLSX
+
+#endif // XLSXDOCUMENT_P_H
diff --git a/internal_system_v1/QXlsx/header/xlsxdrawing_p.h b/internal_system_v1/QXlsx/header/xlsxdrawing_p.h
new file mode 100644
index 0000000..80793cc
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxdrawing_p.h
@@ -0,0 +1,38 @@
+// xlsxdrwaing_p.h
+
+#ifndef QXLSX_DRAWING_H
+#define QXLSX_DRAWING_H
+
+#include <QtGlobal>
+#include <QList>
+#include <QString>
+
+#include "xlsxrelationships_p.h"
+#include "xlsxabstractooxmlfile.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxdrawinganchor_p.h b/internal_system_v1/QXlsx/header/xlsxdrawinganchor_p.h
new file mode 100644
index 0000000..0c8c641
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxdrawinganchor_p.h
@@ -0,0 +1,169 @@
+// xlsxdrawinganchor_p.h
+
+#ifndef QXLSX_XLSXDRAWINGANCHOR_P_H
+#define QXLSX_XLSXDRAWINGANCHOR_P_H
+
+#include <QPoint>
+#include <QSize>
+#include <QString>
+#include <QSharedPointer>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+#include <memory>
+
+#include "xlsxglobal.h"
+
+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(QSharedPointer<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;
+    QSharedPointer<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;
+	// belwo 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
diff --git a/internal_system_v1/QXlsx/header/xlsxformat.h b/internal_system_v1/QXlsx/header/xlsxformat.h
new file mode 100644
index 0000000..8a69e15
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxformat.h
@@ -0,0 +1,262 @@
+// xlsxformat.h
+
+#ifndef QXLSX_FORMAT_H
+#define QXLSX_FORMAT_H
+
+#include <QFont>
+#include <QColor>
+#include <QByteArray>
+#include <QList>
+#include <QExplicitlySharedDataPointer>
+#include <QVariant>
+
+#include "xlsxglobal.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxformat_p.h b/internal_system_v1/QXlsx/header/xlsxformat_p.h
new file mode 100644
index 0000000..0f3240d
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxformat_p.h
@@ -0,0 +1,130 @@
+// xlsxformat_p.h
+#ifndef XLSXFORMAT_P_H
+#define XLSXFORMAT_P_H
+
+#include <QtGlobal>
+#include <QSharedData>
+#include <QMap>
+#include <QSet>
+
+#include "xlsxformat.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxglobal.h b/internal_system_v1/QXlsx/header/xlsxglobal.h
new file mode 100644
index 0000000..a176309
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxglobal.h
@@ -0,0 +1,33 @@
+// xlsxglobal.h
+
+#ifndef XLSXGLOBAL_H
+#define XLSXGLOBAL_H
+
+#include <cstdio>
+#include <string>
+#include <iostream>
+
+#include <QtGlobal>
+#include <QObject>
+#include <QString>
+#include <QVariant>
+#include <QIODevice>
+#include <QByteArray>
+#include <QStringList>
+
+#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
diff --git a/internal_system_v1/QXlsx/header/xlsxmediafile_p.h b/internal_system_v1/QXlsx/header/xlsxmediafile_p.h
new file mode 100644
index 0000000..1c18578
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxmediafile_p.h
@@ -0,0 +1,46 @@
+// xlsxmediafile_p.h
+
+#ifndef QXLSX_XLSXMEDIAFILE_H
+#define QXLSX_XLSXMEDIAFILE_H
+
+#include "xlsxglobal.h"
+
+#include <QString>
+#include <QByteArray>
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxnumformatparser_p.h b/internal_system_v1/QXlsx/header/xlsxnumformatparser_p.h
new file mode 100644
index 0000000..dfa81e9
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxnumformatparser_p.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
diff --git a/internal_system_v1/QXlsx/header/xlsxrelationships_p.h b/internal_system_v1/QXlsx/header/xlsxrelationships_p.h
new file mode 100644
index 0000000..f7259cf
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxrelationships_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+** 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 <QList>
+#include <QString>
+#include <QIODevice>
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxrichstring.h b/internal_system_v1/QXlsx/header/xlsxrichstring.h
new file mode 100644
index 0000000..41a28db
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxrichstring.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+** 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 "xlsxglobal.h"
+#include "xlsxformat.h"
+#include <QVariant>
+#include <QStringList>
+#include <QSharedDataPointer>
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxrichstring_p.h b/internal_system_v1/QXlsx/header/xlsxrichstring_p.h
new file mode 100644
index 0000000..8b00fe3
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxrichstring_p.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
diff --git a/internal_system_v1/QXlsx/header/xlsxsharedstrings_p.h b/internal_system_v1/QXlsx/header/xlsxsharedstrings_p.h
new file mode 100644
index 0000000..c0b3250
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxsharedstrings_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+** 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 <QHash>
+#include <QStringList>
+#include <QIODevice>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+#include "xlsxglobal.h"
+#include "xlsxrichstring.h"
+#include "xlsxabstractooxmlfile.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxsimpleooxmlfile_p.h b/internal_system_v1/QXlsx/header/xlsxsimpleooxmlfile_p.h
new file mode 100644
index 0000000..ba026c9
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxsimpleooxmlfile_p.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 <QString>
+#include <QIODevice>
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxstyles_p.h b/internal_system_v1/QXlsx/header/xlsxstyles_p.h
new file mode 100644
index 0000000..380afd2
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxstyles_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+** 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 <QSharedPointer>
+#include <QHash>
+#include <QList>
+#include <QMap>
+#include <QStringList>
+#include <QVector>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QIODevice>
+
+// class StylesTest;
+
+#include "xlsxglobal.h"
+#include "xlsxformat.h"
+#include "xlsxabstractooxmlfile.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, QSharedPointer<XlsxFormatNumberData> > m_customNumFmtIdMap;
+    QHash<QString, QSharedPointer<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
diff --git a/internal_system_v1/QXlsx/header/xlsxtheme_p.h b/internal_system_v1/QXlsx/header/xlsxtheme_p.h
new file mode 100644
index 0000000..a9a783b
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxtheme_p.h
@@ -0,0 +1,29 @@
+// xlsxtheme_p.h
+
+#ifndef XLSXTHEME_H
+#define XLSXTHEME_H
+
+#include <QtGlobal>
+#include <QString>
+#include <QIODevice>
+
+#include "xlsxabstractooxmlfile.h"
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxutility_p.h b/internal_system_v1/QXlsx/header/xlsxutility_p.h
new file mode 100644
index 0000000..0c8e68f
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxutility_p.h
@@ -0,0 +1,42 @@
+// xlsxutility_p.h
+
+#ifndef XLSXUTILITY_H
+#define XLSXUTILITY_H
+
+#include <QtGlobal>
+#include <QObject>
+#include <QString>
+#include <QPoint>
+#include <QString>
+#include <QStringList>
+#include <QColor>
+#include <QDateTime>
+#include <QDate>
+#include <QTime>
+#include <QVariant>
+
+#include "xlsxglobal.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+class CellReference;
+
+bool parseXsdBoolean(const QString &value, bool defaultValue=false);
+
+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
diff --git a/internal_system_v1/QXlsx/header/xlsxworkbook.h b/internal_system_v1/QXlsx/header/xlsxworkbook.h
new file mode 100644
index 0000000..536ad5f
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxworkbook.h
@@ -0,0 +1,95 @@
+// xlsxworkbook.h
+
+#ifndef XLSXWORKBOOK_H
+#define XLSXWORKBOOK_H
+
+#include <QtGlobal>
+#include <QList>
+#include <QImage>
+#include <QSharedPointer>
+#include <QIODevice>
+
+#include <memory>
+
+#include "xlsxglobal.h"
+#include "xlsxabstractooxmlfile.h"
+#include "xlsxabstractsheet.h"
+
+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(QSharedPointer<Chart> chartFile);
+    QList<QSharedPointer<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<QSharedPointer<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
diff --git a/internal_system_v1/QXlsx/header/xlsxworkbook_p.h b/internal_system_v1/QXlsx/header/xlsxworkbook_p.h
new file mode 100644
index 0000000..7124f30
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxworkbook_p.h
@@ -0,0 +1,74 @@
+// xlsxworkbook_p.h
+
+#ifndef XLSXWORKBOOK_P_H
+#define XLSXWORKBOOK_P_H
+
+#include <QtGlobal>
+#include <QSharedPointer>
+#include <QStringList>
+
+#include "xlsxworkbook.h"
+#include "xlsxabstractooxmlfile_p.h"
+#include "xlsxtheme_p.h"
+#include "xlsxsimpleooxmlfile_p.h"
+#include "xlsxrelationships_p.h"
+
+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);
+
+    QSharedPointer<SharedStrings> sharedStrings;
+    QList<QSharedPointer<AbstractSheet> > sheets;
+    QList<QSharedPointer<SimpleOOXmlFile> > externalLinks;
+    QStringList sheetNames;
+    QSharedPointer<Styles> styles;
+    QSharedPointer<Theme> theme;
+    QList<std::shared_ptr<MediaFile> > mediaFiles;
+    QList<QSharedPointer<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
diff --git a/internal_system_v1/QXlsx/header/xlsxworksheet.h b/internal_system_v1/QXlsx/header/xlsxworksheet.h
new file mode 100644
index 0000000..75a08fc
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxworksheet.h
@@ -0,0 +1,164 @@
+// xlsxworksheet.h
+
+#ifndef XLSXWORKSHEET_H
+#define XLSXWORKSHEET_H
+
+#include <QtGlobal>
+#include <QObject>
+#include <QStringList>
+#include <QMap>
+#include <QVariant>
+#include <QPointF>
+#include <QIODevice>
+#include <QDateTime>
+#include <QUrl>
+#include <QImage>
+
+#include "xlsxabstractsheet.h"
+#include "xlsxcell.h"
+#include "xlsxcellrange.h"
+#include "xlsxcellreference.h"
+#include "xlsxcelllocation.h"
+
+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);
+
+    Cell *cellAt(const CellReference &row_column) const;
+    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);
+
+private:
+    void saveToXmlFile(QIODevice *device) const override;
+    bool loadFromXmlFile(QIODevice *device) override;
+};
+
+QT_END_NAMESPACE_XLSX
+#endif // XLSXWORKSHEET_H
diff --git a/internal_system_v1/QXlsx/header/xlsxworksheet_p.h b/internal_system_v1/QXlsx/header/xlsxworksheet_p.h
new file mode 100644
index 0000000..1fdd552
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxworksheet_p.h
@@ -0,0 +1,252 @@
+// xlsxworksheet_p.h
+
+#ifndef XLSXWORKSHEET_P_H
+#define XLSXWORKSHEET_P_H
+
+#include <QtGlobal>
+#include <QObject>
+#include <QString>
+#include <QVector>
+#include <QImage>
+#include <QSharedPointer>
+
+#include <QRegularExpression>
+
+#include "xlsxworksheet.h"
+#include "xlsxabstractsheet_p.h"
+#include "xlsxcell.h"
+#include "xlsxdatavalidation.h"
+#include "xlsxconditionalformatting.h"
+#include "xlsxcellformula.h"
+
+class QXmlStreamWriter;
+class QXmlStreamReader;
+
+QT_BEGIN_NAMESPACE_XLSX
+
+const int XLSX_ROW_MAX = 1048576;
+const int XLSX_COLUMN_MAX = 16384;
+const int XLSX_STRING_MAX = 32767;
+
+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 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<QSharedPointer<XlsxRowInfo> > getRowInfoList(int rowFirst, int rowLast);
+    QList<QSharedPointer<XlsxColumnInfo> > getColumnInfoList(int colFirst, int colLast);
+    QList<int> getColumnIndexes(int colFirst, int colLast);
+    bool isColumnRangeValid(int colFirst, int colLast);
+
+    SharedStrings *sharedStrings() const;
+
+public:
+    QMap<int, QMap<int, std::shared_ptr<Cell> > > cellTable;
+
+    QMap<int, QMap<int, QString> > comments;
+    QMap<int, QMap<int, QSharedPointer<XlsxHyperlinkData> > > urlTable;
+    QList<CellRange> merges;
+    QMap<int, QSharedPointer<XlsxRowInfo> > rowsInfo;
+    QMap<int, QSharedPointer<XlsxColumnInfo> > colsInfo;
+    QMap<int, QSharedPointer<XlsxColumnInfo> > colsInfoHelper;
+
+    QList<DataValidation> dataValidationsList;
+    QList<ConditionalFormatting> conditionalFormattingList;
+
+    QMap<int, CellFormula> sharedFormulaMap; // shared formula map
+
+    CellRange dimension;
+    int previous_row;
+
+    mutable QMap<int, QString> row_spans;
+    QMap<int, double> row_sizes;
+    QMap<int, double> col_sizes;
+
+    int outline_row_level;
+    int outline_col_level;
+
+    int default_row_height;
+    bool default_row_zeroed;
+
+    // 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
diff --git a/internal_system_v1/QXlsx/header/xlsxzipreader_p.h b/internal_system_v1/QXlsx/header/xlsxzipreader_p.h
new file mode 100644
index 0000000..0a18cbc
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxzipreader_p.h
@@ -0,0 +1,37 @@
+// xlsxzipreader_p.h
+
+#ifndef QXLSX_XLSXZIPREADER_P_H
+#define QXLSX_XLSXZIPREADER_P_H
+
+#include <QScopedPointer>
+#include <QStringList>
+#include <QIODevice>
+
+#include "xlsxglobal.h"
+
+#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
diff --git a/internal_system_v1/QXlsx/header/xlsxzipwriter_p.h b/internal_system_v1/QXlsx/header/xlsxzipwriter_p.h
new file mode 100644
index 0000000..52ae63c
--- /dev/null
+++ b/internal_system_v1/QXlsx/header/xlsxzipwriter_p.h
@@ -0,0 +1,34 @@
+// xlsxzipwriter_p.h
+
+#ifndef QXLSX_ZIPWRITER_H
+#define QXLSX_ZIPWRITER_H
+
+#include <QtGlobal>
+#include <QString>
+#include <QIODevice>
+
+#include "xlsxglobal.h"
+
+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
diff --git a/internal_system_v1/QXlsx/source/xlsxabstractooxmlfile.cpp b/internal_system_v1/QXlsx/source/xlsxabstractooxmlfile.cpp
new file mode 100644
index 0000000..e94a721
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxabstractooxmlfile.cpp
@@ -0,0 +1,97 @@
+// xlsxabstractooxmlfile.cpp
+
+#include <QtGlobal>
+#include <QBuffer>
+#include <QByteArray>
+
+#include "xlsxabstractooxmlfile.h"
+#include "xlsxabstractooxmlfile_p.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+AbstractOOXmlFilePrivate::AbstractOOXmlFilePrivate(AbstractOOXmlFile *q, AbstractOOXmlFile::CreateFlag flag=AbstractOOXmlFile::F_NewFromScratch)
+    : relationships(new Relationships), flag(flag), q_ptr(q)
+{
+
+}
+
+AbstractOOXmlFilePrivate::~AbstractOOXmlFilePrivate()
+{
+    if (relationships) {
+          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
diff --git a/internal_system_v1/QXlsx/source/xlsxabstractsheet.cpp b/internal_system_v1/QXlsx/source/xlsxabstractsheet.cpp
new file mode 100644
index 0000000..88f4db4
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxabstractsheet.cpp
@@ -0,0 +1,186 @@
+// xlsxabstractsheet.cpp
+
+#include <QtGlobal>
+
+#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 cann'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 hiden 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
diff --git a/internal_system_v1/QXlsx/source/xlsxcell.cpp b/internal_system_v1/QXlsx/source/xlsxcell.cpp
new file mode 100644
index 0000000..f3fe4b6
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxcell.cpp
@@ -0,0 +1,364 @@
+// xlsxcell.cpp
+
+#include <cmath>
+
+#include <QtGlobal>
+#include <QDebug>
+#include <QDateTime>
+#include <QDate>
+#include <QTime>
+
+#include "xlsxcell.h"
+#include "xlsxcell_p.h"
+#include "xlsxformat.h"
+#include "xlsxformat_p.h"
+#include "xlsxutility_p.h"
+#include "xlsxworksheet.h"
+#include "xlsxworkbook.h"
+
+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 forumula
+  \value ErrorType        Error type
+  \value SharedStringType Shared string type
+  \value StringType       String type, can be used with forumula
+  \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()
+{
+	if ( NULL != d_ptr )
+		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
diff --git a/internal_system_v1/QXlsx/source/xlsxcellformula.cpp b/internal_system_v1/QXlsx/source/xlsxcellformula.cpp
new file mode 100644
index 0000000..4b1e2b5
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxcellformula.cpp
@@ -0,0 +1,453 @@
+// xlsxcellformula.cpp
+
+#include <QtGlobal>
+#include <QObject>
+#include <QString>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+#include <QDebug>
+
+#include "xlsxcellformula.h"
+#include "xlsxcellformula_p.h"
+#include "xlsxutility_p.h"
+
+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)
+{
+    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-implmented 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-implmented 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-implmented 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-impplmented 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-implmented attribute
+ *
+ * Data table is two-dimentional. 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-implmented attribute
+ *
+ * true if one-dimentional 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-implmented 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-implmented 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
diff --git a/internal_system_v1/QXlsx/source/xlsxcelllocation.cpp b/internal_system_v1/QXlsx/source/xlsxcelllocation.cpp
new file mode 100644
index 0000000..c6342fd
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxcelllocation.cpp
@@ -0,0 +1,23 @@
+// xlsxcelllocation.cpp
+
+#include <QtGlobal>
+#include <QObject>
+#include <QString>
+#include <QVector>
+#include <QList>
+
+#include "xlsxglobal.h"
+#include "xlsxcell.h"
+#include "xlsxcelllocation.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+CellLocation::CellLocation()
+{
+    col = -1;
+    row = -1;
+
+    cell.reset();
+}
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxcellrange.cpp b/internal_system_v1/QXlsx/source/xlsxcellrange.cpp
new file mode 100644
index 0000000..5f54483
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxcellrange.cpp
@@ -0,0 +1,127 @@
+// xlsxcellrange.cpp
+
+#include <QtGlobal>
+#include <QString>
+#include <QPoint>
+#include <QStringList>
+
+#include "xlsxcellrange.h"
+#include "xlsxcellreference.h"
+
+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
diff --git a/internal_system_v1/QXlsx/source/xlsxcellreference.cpp b/internal_system_v1/QXlsx/source/xlsxcellreference.cpp
new file mode 100644
index 0000000..dc28b72
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxcellreference.cpp
@@ -0,0 +1,154 @@
+// xlsxcellreference.cpp
+
+#include "xlsxcellreference.h"
+#include <QStringList>
+#include <QMap>
+
+#include <QRegularExpression>
+
+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)
+{
+    static thread_local QMap<int, QString> col_cache;
+
+    auto it = col_cache.find(col_num);
+    if (it == col_cache.end()) {
+        QString col_str;
+        int remainder;
+        while (col_num) {
+            remainder = col_num % 26;
+            if (remainder == 0)
+                remainder = 26;
+            col_str.prepend(QChar('A'+remainder-1));
+            col_num = (col_num - 1) / 26;
+        }
+        it = col_cache.insert(col_num, col_str);
+    }
+
+    return it.value();
+}
+
+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()
+    : _row(-1), _column(-1)
+{
+}
+
+/*!
+    Constructs the Reference from the given \a row, and \a column.
+*/
+CellReference::CellReference(int row, int column)
+    : _row(row), _column(column)
+{
+}
+
+/*!
+    \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 thread_local 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();
+
+    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
diff --git a/internal_system_v1/QXlsx/source/xlsxchart.cpp b/internal_system_v1/QXlsx/source/xlsxchart.cpp
new file mode 100644
index 0000000..c0a0015
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxchart.cpp
@@ -0,0 +1,2335 @@
+// xlsxchart.cpp
+
+#include <QtGlobal>
+#include <QString>
+#include <QIODevice>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+#include <QDebug>
+
+#include "xlsxchart_p.h"
+#include "xlsxworksheet.h"
+#include "xlsxcellrange.h"
+#include "xlsxutility_p.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+ChartPrivate::ChartPrivate(Chart *q, Chart::CreateFlag flag)
+    : AbstractOOXmlFilePrivate(q, flag), chartType(static_cast<Chart::ChartType>(0))
+{
+
+}
+
+ChartPrivate::~ChartPrivate()
+{
+}
+
+
+
+/*!
+ * \internal
+ */
+Chart::Chart(AbstractSheet *parent, CreateFlag flag)
+    : AbstractOOXmlFile(new ChartPrivate(this, flag))
+{
+    Q_D(Chart);
+
+    d_func()->sheet = parent;
+
+    // d->legendPos = Chart::ChartAxisPos::None;
+    d->legendPos = Chart::None;
+    d->legendOverlay = false;
+    d->majorGridlinesEnabled = false;
+    d->minorGridlinesEnabled = false;
+}
+
+/*!
+ * Destroys the chart.
+ */
+Chart::~Chart()
+{
+}
+
+/*!
+ * Add the data series which is in the range \a range of the \a sheet.
+ */
+void Chart::addSeries(const CellRange &range, AbstractSheet *sheet, bool headerH, bool headerV, bool swapHeaders)
+{
+    Q_D(Chart);
+
+    if (!range.isValid())
+        return;
+    if (sheet && sheet->sheetType() != AbstractSheet::ST_WorkSheet)
+        return;
+    if (!sheet && d->sheet->sheetType() != AbstractSheet::ST_WorkSheet)
+        return;
+
+    QString sheetName = sheet ? sheet->sheetName() : d->sheet->sheetName();
+    //In case sheetName contains space or '
+    sheetName = escapeSheetName(sheetName);
+
+    if (range.columnCount() == 1 || range.rowCount() == 1)
+    {
+        auto series = std::make_shared<XlsxSeries>();
+        series->numberDataSource_numRef = sheetName + QLatin1String("!") + range.toString(true, true);
+        d->seriesList.append(series);
+    }
+    else if ((range.columnCount() < range.rowCount()) || swapHeaders )
+    {
+        //Column based series
+        int firstDataRow = range.firstRow();
+        int firstDataColumn = range.firstColumn();
+
+        QString axDataSouruce_numRef;
+        if (d->chartType == CT_ScatterChart || d->chartType == CT_BubbleChart)
+        {
+            firstDataColumn += 1;
+            CellRange subRange(range.firstRow(), range.firstColumn(), range.lastRow(), range.firstColumn());
+            axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
+        }
+
+        if( headerH )
+        {
+            firstDataRow += 1;
+        }
+        if( headerV )
+        {
+            firstDataColumn += 1;
+        }
+
+        for (int col=firstDataColumn; col<=range.lastColumn(); ++col)
+        {
+            CellRange subRange(firstDataRow, col, range.lastRow(), col);
+            auto series = std::make_shared<XlsxSeries>();
+            series->axDataSource_numRef = axDataSouruce_numRef;
+            series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
+
+            if( headerH )
+            {
+                CellRange subRange(range.firstRow(), col, range.firstRow(), col);
+                series->headerH_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
+            }
+            else
+            {
+                series->headerH_numRef = QString();
+            }
+            if( headerV )
+            {
+                CellRange subRange(firstDataRow, range.firstColumn(), range.lastRow(), range.firstColumn());
+                series->headerV_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
+            }
+            else
+            {
+                series->headerV_numRef = QString();
+            }
+            series->swapHeader = swapHeaders;
+
+            d->seriesList.append(series);
+        }
+
+    }
+    else
+    {
+        //Row based series
+        int firstDataRow = range.firstRow();
+        int firstDataColumn = range.firstColumn();
+
+        QString axDataSouruce_numRef;
+        if (d->chartType == CT_ScatterChart || d->chartType == CT_BubbleChart)
+        {
+            firstDataRow += 1;
+            CellRange subRange(range.firstRow(), range.firstColumn(), range.firstRow(), range.lastColumn());
+            axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
+        }
+
+        if( headerH )
+        {
+            firstDataRow += 1;
+        }
+        if( headerV )
+        {
+            firstDataColumn += 1;
+        }
+
+        for (int row=firstDataRow; row<=range.lastRow(); ++row)
+        {
+            CellRange subRange(row, firstDataColumn, row, range.lastColumn());
+            auto series = std::make_shared<XlsxSeries>();
+            series->axDataSource_numRef = axDataSouruce_numRef;
+            series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
+
+            if( headerH )
+            {
+                CellRange subRange(range.firstRow(), firstDataColumn, range.firstRow(), range.lastColumn());
+                series->headerH_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
+            }
+            else
+            {
+                series->headerH_numRef = QString();
+            }
+
+            if( headerV )
+            {
+                CellRange subRange(row, range.firstColumn(), row, range.firstColumn());
+                series->headerV_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
+            }
+            else
+            {
+                series->headerV_numRef = QString();
+            }
+            series->swapHeader = swapHeaders;
+
+            d->seriesList.append(series);
+        }
+    }
+}
+
+/*!
+ * Set the type of the chart to \a type
+ */
+void Chart::setChartType(ChartType type)
+{
+    Q_D(Chart);
+
+    d->chartType = type;
+}
+
+/*!
+ * \internal
+ *
+ */
+void Chart::setChartStyle(int id)
+{
+    Q_UNUSED(id)
+    //!Todo
+}
+
+void Chart::setAxisTitle(Chart::ChartAxisPos pos, QString axisTitle)
+{
+    Q_D(Chart);
+
+    if ( axisTitle.isEmpty() )
+        return;
+
+    // dev24 : fixed for old compiler
+    if ( pos == Chart::Left )
+    {
+        d->axisNames[ XlsxAxis::Left ] = axisTitle;
+    }
+    else if ( pos == Chart::Top )
+    {
+        d->axisNames[ XlsxAxis::Top ] = axisTitle;
+    }
+    else if ( pos == Chart::Right )
+    {
+        d->axisNames[ XlsxAxis::Right ] = axisTitle;
+    }
+    else if ( pos == Chart::Bottom )
+    {
+        d->axisNames[ XlsxAxis::Bottom ] = axisTitle;
+    }
+
+}
+
+// dev25
+void Chart::setChartTitle(QString strchartTitle)
+{
+    Q_D(Chart);
+
+    d->chartTitle = strchartTitle;
+}
+
+
+void Chart::setChartLegend(Chart::ChartAxisPos legendPos, bool overlay)
+{
+    Q_D(Chart);
+
+    d->legendPos = legendPos;
+    d->legendOverlay = overlay;
+}
+
+
+void Chart::setGridlinesEnable(bool majorGridlinesEnable, bool minorGridlinesEnable)
+{
+    Q_D(Chart);
+
+    d->majorGridlinesEnabled = majorGridlinesEnable;
+    d->minorGridlinesEnabled = minorGridlinesEnable;
+}
+
+
+/*!
+ * \internal
+ */
+void Chart::saveToXmlFile(QIODevice *device) const
+{
+    Q_D(const Chart);
+
+    /*
+        <chartSpace>
+            <chart>
+                <view3D>
+                    <perspective val="30"/>
+                </view3D>
+                <plotArea>
+                    <layout/>
+                    <barChart>
+                    ...
+                    </barChart>
+                    <catAx/>
+                    <valAx/>
+                </plotArea>
+                <legend>
+                ...
+                </legend>
+            </chart>
+            <printSettings>
+            </printSettings>
+        </chartSpace>
+    */
+
+    QXmlStreamWriter writer(device);
+
+    writer.writeStartDocument(QStringLiteral("1.0"), true);
+
+    // L.4.13.2.2 Chart
+    //
+    //  chartSpace is the root node, which contains an element defining the chart,
+    // and an element defining the print settings for the chart.
+
+    writer.writeStartElement(QStringLiteral("c:chartSpace"));
+
+    writer.writeAttribute(QStringLiteral("xmlns:c"),
+                          QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart"));
+    writer.writeAttribute(QStringLiteral("xmlns:a"),
+                          QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main"));
+    writer.writeAttribute(QStringLiteral("xmlns:r"),
+                          QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
+
+    /*
+    * chart is the root element for the chart. If the chart is a 3D chart,
+    * then a view3D element is contained, which specifies the 3D view.
+    * It then has a plot area, which defines a layout and contains an element
+    * that corresponds to, and defines, the type of chart.
+    */
+
+    d->saveXmlChart(writer);
+
+    writer.writeEndElement();// c:chartSpace
+    writer.writeEndDocument();
+}
+
+/*!
+ * \internal
+ */
+bool Chart::loadFromXmlFile(QIODevice *device)
+{
+    Q_D(Chart);
+
+    QXmlStreamReader reader(device);
+    while (!reader.atEnd())
+    {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            if (reader.name() == QLatin1String("chart"))
+            {
+                if (!d->loadXmlChart(reader))
+                {
+                    return false;
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+
+bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("chart"));
+
+//    qDebug() << "-------------- loadXmlChart";
+
+    while (!reader.atEnd())
+    {
+        reader.readNextStartElement();
+
+//        qDebug() << "-------------1- " << reader.name();
+
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+
+            if (reader.name() == QLatin1String("plotArea"))
+            {
+                if (!loadXmlPlotArea(reader))
+                {
+                    return false;
+                }
+            }
+            else if (reader.name() == QLatin1String("title"))
+            {
+                //!Todo
+
+                if ( loadXmlChartTitle(reader) )
+                {
+                }
+
+            }
+//            else if (reader.name() == QLatin1String("legend"))
+//            {
+//                loadXmlChartLegend(reader);
+//                qDebug() << "-------------- loadXmlChartLegend";
+//            }
+        }
+        else if (reader.tokenType() == QXmlStreamReader::EndElement &&
+                 reader.name() == QLatin1String("chart") )
+        {
+            break;
+        }
+    }
+    return true;
+}
+
+// TO DEBUG: loop is not work, when i looping second element.
+/*
+dchrt_CT_PlotArea =
+    element layout { dchrt_CT_Layout }?,
+    (element areaChart { dchrt_CT_AreaChart }
+        | element area3DChart { dchrt_ CT_Area3DChart }
+        | element lineChart { dchrt_CT_LineChart }
+        | element line3DChart { dchrt_CT_Line3DChart }
+        | element stockChart { dchrt_CT_StockChart }
+        | element radarChart { dchrt_CT_RadarChart }
+        | element scatterChart { dchrt_CT_ScatterChart }
+        | element pieChart { dchrt_CT_PieChart }
+        | element pie3DChart { dchrt_CT_Pie3DChart }
+        | element doughnutChart { dchrt_CT_DoughnutChart }
+        | element barChart { dchrt_CT_BarChart }
+        | element bar3DChart { dchrt_CT_Bar3DChart }
+        | element ofPieChart { dchrt_CT_OfPieChart }
+        | element surfaceChart { dchrt_CT_SurfaceChart }
+        | element surface3DChart { dchrt_CT_Surface3DChart }
+        | element bubbleChart { dchrt_CT_BubbleChart })+,
+    (element valAx { dchrt_CT_ValAx }
+        | element catAx { dchrt_CT_CatAx }
+        | element dateAx { dchrt_CT_DateAx }
+        | element serAx { dchrt_CT_SerAx })*,
+    element dTable { dchrt_CT_DTable }?,
+    element spPr { a_CT_ShapeProperties }?,
+    element extLst { dchrt_CT_ExtensionList }?
+ */
+bool ChartPrivate::loadXmlPlotArea(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("plotArea"));
+
+    // TO DEBUG:
+
+    reader.readNext();
+
+    while (!reader.atEnd())
+    {
+//        qDebug() << "-------------2- " << reader.name();
+
+        if (reader.isStartElement())
+        {
+            if (!loadXmlPlotAreaElement(reader))
+            {
+                qDebug() << "[debug] failed to load plotarea element.";
+                return false;
+            }
+            else if (reader.name() == QLatin1String("legend"))  // Why here?
+            {
+                loadXmlChartLegend(reader);
+//                qDebug() << "-------------- loadXmlChartLegend";
+            }
+
+            reader.readNext();
+        }
+        else
+        {
+            reader.readNext();
+        }
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlPlotAreaElement(QXmlStreamReader &reader)
+{
+    if (reader.name() == QLatin1String("layout"))
+    {
+        //!ToDo extract attributes
+        layout = readSubTree(reader);
+    }
+    else if (reader.name().endsWith(QLatin1String("Chart")))
+    {
+        // for pieChart, barChart, ... (choose one)
+        if ( !loadXmlXxxChart(reader) )
+        {
+            qDebug() << "[debug] failed to load chart";
+            return false;
+        }
+    }
+    else if (reader.name() == QLatin1String("catAx")) // choose one : catAx, dateAx, serAx, valAx
+    {
+        // qDebug() << "loadXmlAxisCatAx()";
+        loadXmlAxisCatAx(reader);
+    }
+    else if (reader.name() == QLatin1String("dateAx")) // choose one : catAx, dateAx, serAx, valAx
+    {
+        // qDebug() << "loadXmlAxisDateAx()";
+        loadXmlAxisDateAx(reader);
+    }
+    else if (reader.name() == QLatin1String("serAx")) // choose one : catAx, dateAx, serAx, valAx
+    {
+        // qDebug() << "loadXmlAxisSerAx()";
+        loadXmlAxisSerAx(reader);
+    }
+    else if (reader.name() == QLatin1String("valAx")) // choose one : catAx, dateAx, serAx, valAx
+    {
+        // qDebug() << "loadXmlAxisValAx()";
+        loadXmlAxisValAx(reader);
+    }
+    else if (reader.name() == QLatin1String("dTable"))
+    {
+        //!ToDo
+        // dTable "CT_DTable"
+        // reader.skipCurrentElement();
+    }
+    else if (reader.name() == QLatin1String("spPr"))
+    {
+        //!ToDo
+        // spPr "a:CT_ShapeProperties"
+        // reader.skipCurrentElement();
+    }
+    else if (reader.name() == QLatin1String("extLst"))
+    {
+        //!ToDo
+        // extLst "CT_ExtensionList"
+        // reader.skipCurrentElement();
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlXxxChart(QXmlStreamReader &reader)
+{
+    const auto& name = reader.name();
+
+    if (name == QLatin1String("areaChart"))
+    {
+        chartType = Chart::CT_AreaChart;
+    }
+    else if (name == QLatin1String("area3DChart"))
+    {
+        chartType = Chart::CT_Area3DChart;
+    }
+    else if (name == QLatin1String("lineChart"))
+    {
+        chartType = Chart::CT_LineChart;
+    }
+    else if (name == QLatin1String("line3DChart"))
+    {
+        chartType = Chart::CT_Line3DChart;
+    }
+    else if (name == QLatin1String("stockChart"))
+    {
+        chartType = Chart::CT_StockChart;
+    }
+    else if (name == QLatin1String("radarChart"))
+    {
+        chartType = Chart::CT_RadarChart;
+    }
+    else if (name == QLatin1String("scatterChart"))
+    {
+        chartType = Chart::CT_ScatterChart;
+    }
+    else if (name == QLatin1String("pieChart"))
+    {
+        chartType = Chart::CT_PieChart;
+    }
+    else if (name == QLatin1String("pie3DChart"))
+    {
+        chartType = Chart::CT_Pie3DChart;
+    }
+    else if (name == QLatin1String("doughnutChart"))
+    {
+        chartType = Chart::CT_DoughnutChart;
+    }
+    else if (name == QLatin1String("barChart"))
+    {
+        chartType = Chart::CT_BarChart;
+    }
+    else if (name == QLatin1String("bar3DChart"))
+    {
+        chartType = Chart::CT_Bar3DChart;
+    }
+    else if (name == QLatin1String("ofPieChart"))
+    {
+        chartType = Chart::CT_OfPieChart;
+    }
+    else if (name == QLatin1String("surfaceChart"))
+    {
+        chartType = Chart::CT_SurfaceChart;
+    }
+    else if (name == QLatin1String("surface3DChart"))
+    {
+        chartType = Chart::CT_Surface3DChart;
+    }
+    else if (name == QLatin1String("bubbleChart"))
+    {
+        chartType = Chart::CT_BubbleChart;
+    }
+    else
+    {
+        qDebug() << "[undefined chart type] " << name;
+        chartType = Chart::CT_NoStatementChart;
+        return false;
+    }
+
+    while( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            // dev57
+
+            if ( reader.name() == QLatin1String("ser") )
+            {
+                loadXmlSer(reader);
+            }
+            else if (reader.name() == QLatin1String("varyColors"))
+            {
+            }
+            else if (reader.name() == QLatin1String("barDir"))
+            {
+            }
+            else if (reader.name() == QLatin1String("axId"))
+            {
+                //
+
+            }
+            else if (reader.name() == QLatin1String("scatterStyle"))
+            {
+            }
+            else if (reader.name() == QLatin1String("holeSize"))
+            {
+            }
+            else
+            {
+            }
+
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name() == name )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlSer(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("ser"));
+
+    auto series = std::make_shared<XlsxSeries>();
+    seriesList.append(series);
+
+    while ( !reader.atEnd() &&
+            !(reader.tokenType() == QXmlStreamReader::EndElement &&
+             reader.name() == QLatin1String("ser")) )
+    {
+        if (reader.readNextStartElement())
+        {
+            //TODO beide Header noch auswerten RTR 2019.11
+            const auto& name = reader.name();
+            if ( name == QLatin1String("tx") )
+            {
+                while ( !reader.atEnd() &&
+                        !(reader.tokenType() == QXmlStreamReader::EndElement &&
+                         reader.name() == name))
+                {
+                    if (reader.readNextStartElement())
+                    {
+                        if (reader.name() == QLatin1String("strRef"))
+                            series->headerV_numRef = loadXmlStrRef(reader);
+                    }
+                }
+            }
+            else if ( name == QLatin1String("cat") ||
+                 name == QLatin1String("xVal") )
+            {
+                while ( !reader.atEnd() &&
+                        !(reader.tokenType() == QXmlStreamReader::EndElement &&
+                         reader.name() == name))
+                {
+                    if (reader.readNextStartElement())
+                    {
+                        if (reader.name() == QLatin1String("numRef"))
+                            series->axDataSource_numRef = loadXmlNumRef(reader);
+                        else
+                        if (reader.name() == QLatin1String("strRef"))
+                            series->headerH_numRef = loadXmlStrRef(reader);
+                    }
+                }
+            }
+            else if (name == QLatin1String("val") || name == QLatin1String("yVal"))
+            {
+                while ( !reader.atEnd() &&
+                        !(reader.tokenType() == QXmlStreamReader::EndElement &&
+                        reader.name() == name))
+                {
+                    if (reader.readNextStartElement())
+                    {
+                        if (reader.name() == QLatin1String("numRef"))
+                            series->numberDataSource_numRef = loadXmlNumRef(reader);
+                    }
+                }
+            }
+            else if (name == QLatin1String("extLst"))
+            {
+                while ( !reader.atEnd() &&
+                        !(reader.tokenType() == QXmlStreamReader::EndElement &&
+                         reader.name() == name))
+                {
+                    reader.readNextStartElement();
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+
+QString ChartPrivate::loadXmlNumRef(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("numRef"));
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("numRef")))
+    {
+        if (reader.readNextStartElement())
+        {
+            if (reader.name() == QLatin1String("f"))
+                return reader.readElementText();
+        }
+    }
+
+    return QString();
+}
+
+
+QString ChartPrivate::loadXmlStrRef(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("strRef"));
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("strRef")))
+    {
+        if (reader.readNextStartElement())
+        {
+            if (reader.name() == QLatin1String("f"))
+                return reader.readElementText();
+        }
+    }
+
+    return QString();
+}
+
+
+void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const
+{
+    //----------------------------------------------------
+    // c:chart
+    writer.writeStartElement(QStringLiteral("c:chart"));
+
+    //----------------------------------------------------
+    // c:title
+
+    saveXmlChartTitle(writer); // write 'chart title'
+
+    //----------------------------------------------------
+    // c:plotArea
+
+    writer.writeStartElement(QStringLiteral("c:plotArea"));
+
+    // a little workaround for Start- and EndElement with starting ">" and ending without ">"
+    writer.device()->write("><c:layout>"); //layout
+    writer.device()->write(layout.toUtf8());
+    writer.device()->write("</c:layout"); //layout
+
+    // dev35
+    switch (chartType)
+    {
+        case Chart::CT_AreaChart:       saveXmlAreaChart(writer); break;
+        case Chart::CT_Area3DChart:     saveXmlAreaChart(writer); break;
+        case Chart::CT_LineChart:       saveXmlLineChart(writer); break;
+        case Chart::CT_Line3DChart:     saveXmlLineChart(writer); break;
+        case Chart::CT_StockChart: break;
+        case Chart::CT_RadarChart: break;
+        case Chart::CT_ScatterChart:    saveXmlScatterChart(writer); break;
+        case Chart::CT_PieChart:        saveXmlPieChart(writer); break;
+        case Chart::CT_Pie3DChart:      saveXmlPieChart(writer); break;
+        case Chart::CT_DoughnutChart:   saveXmlDoughnutChart(writer); break;
+        case Chart::CT_BarChart:        saveXmlBarChart(writer); break;
+        case Chart::CT_Bar3DChart:      saveXmlBarChart(writer); break;
+        case Chart::CT_OfPieChart: break;
+        case Chart::CT_SurfaceChart:  break;
+        case Chart::CT_Surface3DChart: break;
+        case Chart::CT_BubbleChart:  break;
+        default:  break;
+    }
+
+    saveXmlAxis(writer); // c:catAx, c:valAx, c:serAx, c:dateAx (choose one)
+
+    //!TODO: write element
+    // c:dTable CT_DTable
+    // c:spPr   CT_ShapeProperties
+    // c:extLst CT_ExtensionList
+
+    writer.writeEndElement(); // c:plotArea
+
+    // c:legend
+    saveXmlChartLegend(writer); // c:legend
+
+    writer.writeEndElement(); // c:chart
+}
+
+bool ChartPrivate::loadXmlChartTitle(QXmlStreamReader &reader)
+{
+    //!TODO : load chart title
+
+    Q_ASSERT(reader.name() == QLatin1String("title"));
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("title")))
+    {
+        if (reader.readNextStartElement())
+        {
+            if (reader.name() == QLatin1String("tx")) // c:tx
+                return loadXmlChartTitleTx(reader);
+        }
+    }
+
+    return false;
+}
+
+bool ChartPrivate::loadXmlChartTitleTx(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("tx"));
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("tx")))
+    {
+        if (reader.readNextStartElement())
+        {
+            if (reader.name() == QLatin1String("rich")) // c:rich
+                return loadXmlChartTitleTxRich(reader);
+        }
+    }
+
+    return false;
+}
+
+bool ChartPrivate::loadXmlChartTitleTxRich(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("rich"));
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("rich")))
+    {
+        if (reader.readNextStartElement())
+        {
+            if (reader.name() == QLatin1String("p")) // a:p
+                return loadXmlChartTitleTxRichP(reader);
+        }
+    }
+
+    return false;
+}
+
+bool ChartPrivate::loadXmlChartTitleTxRichP(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("p"));
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("p")))
+    {
+        if (reader.readNextStartElement())
+        {
+            if (reader.name() == QLatin1String("r")) // a:r
+                return loadXmlChartTitleTxRichP_R(reader);
+        }
+    }
+
+    return false;
+}
+
+bool ChartPrivate::loadXmlChartTitleTxRichP_R(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("r"));
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("r")))
+    {
+        if (reader.readNextStartElement())
+        {
+            if (reader.name() == QLatin1String("t")) // a:t
+            {
+                QString textValue = reader.readElementText();
+                this->chartTitle = textValue;
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+
+// write 'chart title'
+void ChartPrivate::saveXmlChartTitle(QXmlStreamWriter &writer) const
+{
+    if ( chartTitle.isEmpty() )
+        return;
+
+    writer.writeStartElement(QStringLiteral("c:title"));
+    /*
+    <xsd:complexType name="CT_Title">
+        <xsd:sequence>
+            <xsd:element name="tx"      type="CT_Tx"                minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="layout"  type="CT_Layout"            minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="overlay" type="CT_Boolean"           minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="spPr"    type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="txPr"    type="a:CT_TextBody"        minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="extLst"  type="CT_ExtensionList"     minOccurs="0" maxOccurs="1"/>
+        </xsd:sequence>
+    </xsd:complexType>
+    */
+
+        writer.writeStartElement(QStringLiteral("c:tx"));
+        /*
+        <xsd:complexType name="CT_Tx">
+            <xsd:sequence>
+                <xsd:choice     minOccurs="1"   maxOccurs="1">
+                <xsd:element    name="strRef"   type="CT_StrRef"        minOccurs="1" maxOccurs="1"/>
+                <xsd:element    name="rich"     type="a:CT_TextBody"    minOccurs="1" maxOccurs="1"/>
+                </xsd:choice>
+            </xsd:sequence>
+        </xsd:complexType>
+        */
+
+            writer.writeStartElement(QStringLiteral("c:rich"));
+            /*
+            <xsd:complexType name="CT_TextBody">
+                <xsd:sequence>
+                    <xsd:element name="bodyPr"      type="CT_TextBodyProperties"    minOccurs=" 1"  maxOccurs="1"/>
+                    <xsd:element name="lstStyle"    type="CT_TextListStyle"         minOccurs="0"   maxOccurs="1"/>
+                    <xsd:element name="p"           type="CT_TextParagraph"         minOccurs="1"   maxOccurs="unbounded"/>
+                </xsd:sequence>
+            </xsd:complexType>
+            */
+
+                writer.writeEmptyElement(QStringLiteral("a:bodyPr")); // <a:bodyPr/>
+                /*
+                <xsd:complexType name="CT_TextBodyProperties">
+                    <xsd:sequence>
+                        <xsd:element name="prstTxWarp" type="CT_PresetTextShape" minOccurs="0" maxOccurs="1"/>
+                        <xsd:group ref="EG_TextAutofit" minOccurs="0" maxOccurs="1"/>
+                        <xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0" maxOccurs="1"/>
+                        <xsd:group ref="EG_Text3D" minOccurs="0" maxOccurs="1"/>
+                        <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
+                    </xsd:sequence>
+                    <xsd:attribute name="rot" type="ST_Angle" use="optional"/>
+                    <xsd:attribute name="spcFirstLastPara" type="xsd:boolean" use="optional"/>
+                    <xsd:attribute name="vertOverflow" type="ST_TextVertOverflowType" use="optional"/>
+                    <xsd:attribute name="horzOverflow" type="ST_TextHorzOverflowType" use="optional"/>
+                    <xsd:attribute name="vert" type="ST_TextVerticalType" use="optional"/>
+                    <xsd:attribute name="wrap" type="ST_TextWrappingType" use="optional"/>
+                    <xsd:attribute name="lIns" type="ST_Coordinate32" use="optional"/>
+                    <xsd:attribute name="tIns" type="ST_Coordinate32" use="optional"/>
+                    <xsd:attribute name="rIns" type="ST_Coordinate32" use="optional"/>
+                    <xsd:attribute name="bIns" type="ST_Coordinate32" use="optional"/>
+                    <xsd:attribute name="numCol" type="ST_TextColumnCount" use="optional"/>
+                    <xsd:attribute name="spcCol" type="ST_PositiveCoordinate32" use="optional"/>
+                    <xsd:attribute name="rtlCol" type="xsd:boolean" use="optional"/>
+                    <xsd:attribute name="fromWordArt" type="xsd:boolean" use="optional"/>
+                    <xsd:attribute name="anchor" type="ST_TextAnchoringType" use="optional"/>
+                    <xsd:attribute name="anchorCtr" type="xsd:boolean" use="optional"/>
+                    <xsd:attribute name="forceAA" type="xsd:boolean" use="optional"/>
+                    <xsd:attribute name="upright" type="xsd:boolean" use="optional" default="false"/>
+                    <xsd:attribute name="compatLnSpc" type="xsd:boolean" use="optional"/>
+                </xsd:complexType>
+                 */
+
+                writer.writeEmptyElement(QStringLiteral("a:lstStyle")); // <a:lstStyle/>
+
+                writer.writeStartElement(QStringLiteral("a:p"));
+                /*
+                <xsd:complexType name="CT_TextParagraph">
+                    <xsd:sequence>
+                        <xsd:element    name="pPr"          type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/>
+                        <xsd:group      ref="EG_TextRun"    minOccurs="0" maxOccurs="unbounded"/>
+                        <xsd:element    name="endParaRPr"   type="CT_TextCharacterProperties" minOccurs="0"
+                        maxOccurs="1"/>
+                    </xsd:sequence>
+                </xsd:complexType>
+                 */
+
+                    // <a:pPr lvl="0">
+                    writer.writeStartElement(QStringLiteral("a:pPr"));
+
+                        writer.writeAttribute(QStringLiteral("lvl"), QStringLiteral("0"));
+
+                        // <a:defRPr b="0"/>
+                        writer.writeStartElement(QStringLiteral("a:defRPr"));
+
+                            writer.writeAttribute(QStringLiteral("b"), QStringLiteral("0"));
+
+                        writer.writeEndElement();  // a:defRPr
+
+                    writer.writeEndElement();  // a:pPr
+
+                /*
+                <xsd:group name="EG_TextRun">
+                    <xsd:choice>
+                        <xsd:element name="r"   type="CT_RegularTextRun"/>
+                        <xsd:element name="br"  type="CT_TextLineBreak"/>
+                        <xsd:element name="fld" type="CT_TextField"/>
+                    </xsd:choice>
+                </xsd:group>
+                */
+
+                writer.writeStartElement(QStringLiteral("a:r"));
+                /*
+                <xsd:complexType name="CT_RegularTextRun">
+                    <xsd:sequence>
+                        <xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0" maxOccurs="1"/>
+                        <xsd:element name="t"   type="xsd:string" minOccurs="1" maxOccurs="1"/>
+                    </xsd:sequence>
+                </xsd:complexType>
+                 */
+
+                    // <a:t>chart name</a:t>
+                    writer.writeTextElement(QStringLiteral("a:t"), chartTitle);
+
+                writer.writeEndElement();  // a:r
+
+                writer.writeEndElement();  // a:p
+
+            writer.writeEndElement();  // c:rich
+
+        writer.writeEndElement();  // c:tx
+
+        // <c:overlay val="0"/>
+        writer.writeStartElement(QStringLiteral("c:overlay"));
+            writer.writeAttribute(QStringLiteral("val"), QStringLiteral("0"));
+        writer.writeEndElement();  // c:overlay
+
+    writer.writeEndElement();  // c:title
+}
+// }}
+
+
+// write 'chart legend'
+void ChartPrivate::saveXmlChartLegend(QXmlStreamWriter &writer) const
+{
+    if ( legendPos == Chart::None )
+        return;
+
+//    <c:legend>
+//    <c:legendPos val="r"/>
+//    <c:overlay val="0"/>
+//    </c:legend>
+
+    writer.writeStartElement(QStringLiteral("c:legend"));
+
+        writer.writeStartElement(QStringLiteral("c:legendPos"));
+
+            QString pos;
+            switch( legendPos )
+            {
+                //case Chart::ChartAxisPos::Right:
+                case Chart::Right :
+                    pos = QStringLiteral("r");
+                    break;
+
+                // case Chart::ChartAxisPos::Left:
+                case Chart::Left :
+                    pos = QStringLiteral("l");
+                    break;
+
+                // case Chart::ChartAxisPos::Top:
+                case Chart::Top :
+                    pos = QStringLiteral("t");
+                    break;
+
+                // case Chart::ChartAxisPos::Bottom:
+                case Chart::Bottom :
+                    pos = QStringLiteral("b");
+                    break;
+
+                default:
+                    pos = QStringLiteral("r");
+                    break;
+            }
+
+            writer.writeAttribute(QStringLiteral("val"), pos);
+
+        writer.writeEndElement();  // c:legendPos
+
+        writer.writeStartElement(QStringLiteral("c:overlay"));
+
+            if( legendOverlay )
+            {
+                writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1"));
+            }
+            else
+            {
+                writer.writeAttribute(QStringLiteral("val"), QStringLiteral("0"));
+            }
+
+        writer.writeEndElement();  // c:overlay
+
+    writer.writeEndElement(); // c:legend
+}
+
+
+void ChartPrivate::saveXmlPieChart(QXmlStreamWriter &writer) const
+{
+    QString name = chartType == Chart::CT_PieChart ? QStringLiteral("c:pieChart") : QStringLiteral("c:pie3DChart");
+
+    writer.writeStartElement(name);
+
+    //Do the same behavior as Excel, Pie prefer varyColors
+    writer.writeEmptyElement(QStringLiteral("c:varyColors"));
+    writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1"));
+
+    for (int i=0; i<seriesList.size(); ++i)
+        saveXmlSer(writer, seriesList[i].get(), i);
+
+    writer.writeEndElement(); //pieChart, pie3DChart
+}
+
+void ChartPrivate::saveXmlBarChart(QXmlStreamWriter &writer) const
+{
+    QString name = chartType == Chart::CT_BarChart ? QStringLiteral("c:barChart") : QStringLiteral("c:bar3DChart");
+
+    writer.writeStartElement(name);
+
+    writer.writeEmptyElement(QStringLiteral("c:barDir"));
+    writer.writeAttribute(QStringLiteral("val"), QStringLiteral("col"));
+
+    for ( int i = 0 ; i < seriesList.size() ; ++i )
+    {
+        saveXmlSer(writer, seriesList[i].get(), i);
+    }
+
+    if ( axisList.isEmpty() )
+    {
+        const_cast<ChartPrivate*>(this)->axisList.append(
+                    std::make_shared<XlsxAxis>( XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1, axisNames[XlsxAxis::Bottom] ));
+
+        const_cast<ChartPrivate*>(this)->axisList.append(
+                    std::make_shared<XlsxAxis>( XlsxAxis::T_Val, XlsxAxis::Left, 1, 0, axisNames[XlsxAxis::Left] ));
+    }
+
+
+    // Note: Bar3D have 2~3 axes
+    // int axisListSize = axisList.size();
+    // [dev62]
+    // Q_ASSERT( axisListSize == 2 ||
+    //          ( axisListSize == 3 && chartType == Chart::CT_Bar3DChart ) );
+
+    for ( int i = 0 ; i < axisList.size() ; ++i )
+    {
+        writer.writeEmptyElement(QStringLiteral("c:axId"));
+        writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
+    }
+
+    writer.writeEndElement(); //barChart, bar3DChart
+}
+
+void ChartPrivate::saveXmlLineChart(QXmlStreamWriter &writer) const
+{
+    QString name = chartType==Chart::CT_LineChart ? QStringLiteral("c:lineChart") : QStringLiteral("c:line3DChart");
+
+    writer.writeStartElement(name);
+
+    // writer.writeEmptyElement(QStringLiteral("grouping")); // dev22
+
+    for (int i=0; i<seriesList.size(); ++i)
+        saveXmlSer(writer, seriesList[i].get(), i);
+
+    if (axisList.isEmpty())
+    {
+        const_cast<ChartPrivate*>(this)->axisList.append(std::make_shared<XlsxAxis>(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1, axisNames[XlsxAxis::Bottom] ));
+        const_cast<ChartPrivate*>(this)->axisList.append(std::make_shared<XlsxAxis>(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0, axisNames[XlsxAxis::Left] ));
+        if (chartType==Chart::CT_Line3DChart)
+            const_cast<ChartPrivate*>(this)->axisList.append(std::make_shared<XlsxAxis>(XlsxAxis::T_Ser, XlsxAxis::Bottom, 2, 0));
+    }
+
+    Q_ASSERT((axisList.size()==2||chartType==Chart::CT_LineChart)|| (axisList.size()==3 && chartType==Chart::CT_Line3DChart));
+
+    for (int i=0; i<axisList.size(); ++i)
+    {
+        writer.writeEmptyElement(QStringLiteral("c:axId"));
+        writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
+    }
+
+    writer.writeEndElement(); //lineChart, line3DChart
+}
+
+void ChartPrivate::saveXmlScatterChart(QXmlStreamWriter &writer) const
+{
+    const QString name = QStringLiteral("c:scatterChart");
+
+    writer.writeStartElement(name);
+
+    writer.writeEmptyElement(QStringLiteral("c:scatterStyle"));
+
+    for (int i=0; i<seriesList.size(); ++i)
+        saveXmlSer(writer, seriesList[i].get(), i);
+
+    if (axisList.isEmpty())
+    {
+        const_cast<ChartPrivate*>(this)->axisList.append(
+                    std::make_shared<XlsxAxis>(XlsxAxis::T_Val, XlsxAxis::Bottom, 0, 1, axisNames[XlsxAxis::Bottom] ));
+        const_cast<ChartPrivate*>(this)->axisList.append(
+                    std::make_shared<XlsxAxis>(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0, axisNames[XlsxAxis::Left] ));
+    }
+
+    int axisListSize = axisList.size();
+    Q_ASSERT(axisListSize == 2);
+
+    for (int i=0; i<axisList.size(); ++i)
+    {
+        writer.writeEmptyElement(QStringLiteral("c:axId"));
+        writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
+    }
+
+    writer.writeEndElement(); //c:scatterChart
+}
+
+void ChartPrivate::saveXmlAreaChart(QXmlStreamWriter &writer) const
+{
+    QString name = chartType==Chart::CT_AreaChart ? QStringLiteral("c:areaChart") : QStringLiteral("c:area3DChart");
+
+    writer.writeStartElement(name);
+
+    // writer.writeEmptyElement(QStringLiteral("grouping")); // dev22
+
+    for (int i=0; i<seriesList.size(); ++i)
+        saveXmlSer(writer, seriesList[i].get(), i);
+
+    if (axisList.isEmpty())
+    {
+        const_cast<ChartPrivate*>(this)->axisList.append(std::make_shared<XlsxAxis>(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1));
+        const_cast<ChartPrivate*>(this)->axisList.append(std::make_shared<XlsxAxis>(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0));
+    }
+
+    //Note: Area3D have 2~3 axes
+    Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Area3DChart));
+
+    for (int i=0; i<axisList.size(); ++i)
+    {
+        writer.writeEmptyElement(QStringLiteral("c:axId"));
+        writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
+    }
+
+    writer.writeEndElement(); //lineChart, line3DChart
+}
+
+void ChartPrivate::saveXmlDoughnutChart(QXmlStreamWriter &writer) const
+{
+    QString name = QStringLiteral("c:doughnutChart");
+
+    writer.writeStartElement(name);
+
+    writer.writeEmptyElement(QStringLiteral("c:varyColors"));
+    writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1"));
+
+    for (int i=0; i<seriesList.size(); ++i)
+        saveXmlSer(writer, seriesList[i].get(), i);
+
+    writer.writeStartElement(QStringLiteral("c:holeSize"));
+    writer.writeAttribute(QStringLiteral("val"), QString::number(50));
+
+    writer.writeEndElement();
+}
+
+void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const
+{
+
+    writer.writeStartElement(QStringLiteral("c:ser"));
+    writer.writeEmptyElement(QStringLiteral("c:idx"));
+    writer.writeAttribute(QStringLiteral("val"), QString::number(id));
+    writer.writeEmptyElement(QStringLiteral("c:order"));
+    writer.writeAttribute(QStringLiteral("val"), QString::number(id));
+
+    QString header1;
+    QString header2;
+    if( ser->swapHeader )
+    {
+        header1 = ser->headerH_numRef;
+        header2 = ser->headerV_numRef;
+    }
+    else
+    {
+        header1 = ser->headerV_numRef;
+        header2 = ser->headerH_numRef;
+    }
+
+    if( !header1.isEmpty() )
+    {
+        writer.writeStartElement(QStringLiteral("c:tx"));
+        writer.writeStartElement(QStringLiteral("c:strRef"));
+        writer.writeTextElement(QStringLiteral("c:f"), header1);
+        writer.writeEndElement();
+        writer.writeEndElement();
+    }
+    if( !header2.isEmpty() )
+    {
+        writer.writeStartElement(QStringLiteral("c:cat"));
+        writer.writeStartElement(QStringLiteral("c:strRef"));
+        writer.writeTextElement(QStringLiteral("c:f"), header2);
+        writer.writeEndElement();
+        writer.writeEndElement();
+    }
+
+#if 0
+    if (!ser->axDataSource_numRef.isEmpty())
+    {
+        if (chartType == Chart::CT_ScatterChart || chartType == Chart::CT_BubbleChart)
+        {
+            writer.writeStartElement(QStringLiteral("c:xVal"));
+        }
+        else
+        {
+            writer.writeStartElement(QStringLiteral("c:cat"));
+        }
+
+        writer.writeStartElement(QStringLiteral("c:numRef"));
+        writer.writeTextElement(QStringLiteral("c:f"), ser->axDataSource_numRef);
+        writer.writeEndElement();//c:numRef
+        writer.writeEndElement();//c:cat or c:xVal
+    }
+#endif
+
+    if (!ser->numberDataSource_numRef.isEmpty())
+    {
+        if (chartType == Chart::CT_ScatterChart || chartType == Chart::CT_BubbleChart)
+            writer.writeStartElement(QStringLiteral("c:yVal"));
+        else
+            writer.writeStartElement(QStringLiteral("c:val"));
+        writer.writeStartElement(QStringLiteral("c:numRef"));
+        writer.writeTextElement(QStringLiteral("c:f"), ser->numberDataSource_numRef);
+        writer.writeEndElement();//c:numRef
+        writer.writeEndElement();//c:val or c:yVal
+    }
+
+    writer.writeEndElement();//c:ser
+}
+
+bool ChartPrivate::loadXmlAxisCatAx(QXmlStreamReader &reader)
+{
+
+    auto axis = std::make_shared<XlsxAxis>();
+    axis->type = XlsxAxis::T_Cat;
+    axisList.append(axis);
+
+    // load EG_AxShared
+    if ( ! loadXmlAxisEG_AxShared( reader, axis.get() ) )
+    {
+        qDebug() << "failed to load EG_AxShared";
+        return false;
+    }
+
+    //!TODO: load element
+    // auto
+    // lblAlgn
+    // lblOffset
+    // tickLblSkip
+    // tickMarkSkip
+    // noMultiLvlLbl
+    // extLst
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisDateAx(QXmlStreamReader &reader)
+{
+
+    auto axis = std::make_shared<XlsxAxis>();
+    axis->type = XlsxAxis::T_Date;
+    axisList.append(axis);
+
+    // load EG_AxShared
+    if ( ! loadXmlAxisEG_AxShared( reader, axis.get() ) )
+    {
+        qDebug() << "failed to load EG_AxShared";
+        return false;
+    }
+
+    //!TODO: load element
+    // auto
+    // lblOffset
+    // baseTimeUnit
+    // majorUnit
+    // majorTimeUnit
+    // minorUnit
+    // minorTimeUnit
+    // extLst
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisSerAx(QXmlStreamReader &reader)
+{
+
+    auto axis = std::make_shared<XlsxAxis>();
+    axis->type = XlsxAxis::T_Ser;
+    axisList.append(axis);
+
+    // load EG_AxShared
+    if ( ! loadXmlAxisEG_AxShared( reader, axis.get() ) )
+    {
+        qDebug() << "failed to load EG_AxShared";
+        return false;
+    }
+
+    //!TODO: load element
+    // tickLblSkip
+    // tickMarkSkip
+    // extLst
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisValAx(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("valAx"));
+
+    auto axis = std::make_shared<XlsxAxis>();
+    axis->type = XlsxAxis::T_Val;
+    axisList.append(axis);
+
+    if ( ! loadXmlAxisEG_AxShared( reader, axis.get() ) )
+    {
+        qDebug() << "failed to load EG_AxShared";
+        return false;
+    }
+
+    //!TODO: load element
+    // crossBetween
+    // majorUnit
+    // minorUnit
+    // dispUnits
+    // extLst
+
+    return true;
+}
+
+/*
+<xsd:group name="EG_AxShared">
+    <xsd:sequence>
+        <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> (*)(M)
+        <xsd:element name="scaling" type="CT_Scaling" minOccurs="1" maxOccurs="1"/> (*)(M)
+        <xsd:element name="delete" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="axPos" type="CT_AxPos" minOccurs="1" maxOccurs="1"/> (*)(M)
+        <xsd:element name="majorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="minorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="title" type="CT_Title" minOccurs="0" maxOccurs="1"/> (*)
+        <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="majorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="minorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="tickLblPos" type="CT_TickLblPos" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="crossAx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> (*)(M)
+        <xsd:choice minOccurs="0" maxOccurs="1">
+            <xsd:element name="crosses" type="CT_Crosses" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="crossesAt" type="CT_Double" minOccurs="1" maxOccurs="1"/>
+        </xsd:choice>
+    </xsd:sequence>
+</xsd:group>
+*/
+bool ChartPrivate::loadXmlAxisEG_AxShared(QXmlStreamReader &reader, XlsxAxis* axis)
+{
+    Q_ASSERT( NULL != axis );
+    Q_ASSERT( reader.name().endsWith(QLatin1String("Ax")) );
+    QString name = reader.name().toString(); //
+
+    while ( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if ( reader.tokenType() == QXmlStreamReader::StartElement )
+        {
+            // qDebug() << "[debug]" << QTime::currentTime() << reader.name().toString();
+
+            if ( reader.name() == QLatin1String("axId") ) // mandatory element
+            {
+                // dev57
+                uint axId = reader.attributes().value(QStringLiteral("val")).toUInt(); // for Qt5.1
+                axis->axisId = axId;
+            }
+            else if ( reader.name() == QLatin1String("scaling") )
+            {
+                // mandatory element
+
+                loadXmlAxisEG_AxShared_Scaling(reader, axis);
+            }
+            else if ( reader.name() == QLatin1String("delete") )
+            {
+                //!TODO
+            }
+            else if ( reader.name() == QLatin1String("axPos") )
+            {
+                // mandatory element
+
+                QString axPosVal = reader.attributes().value(QLatin1String("val")).toString();
+
+                if ( axPosVal == QLatin1String("l") ) { axis->axisPos = XlsxAxis::Left; }
+                else if ( axPosVal == QLatin1String("r") ) { axis->axisPos = XlsxAxis::Right; }
+                else if ( axPosVal == QLatin1String("t") ) { axis->axisPos = XlsxAxis::Top; }
+                else if ( axPosVal == QLatin1String("b") ) { axis->axisPos = XlsxAxis::Bottom; }
+            }
+            else if ( reader.name() == QLatin1String("majorGridlines") )
+            {
+                //!TODO anything else?
+                majorGridlinesEnabled = true;
+            }
+            else if ( reader.name() == QLatin1String("minorGridlines") )
+            {
+                //!TODO anything else?
+                minorGridlinesEnabled = true;
+            }
+            else if ( reader.name() == QLatin1String("title") )
+            {
+                // title
+                if ( !loadXmlAxisEG_AxShared_Title(reader, axis) )
+                {
+                    qDebug() << "failed to load EG_AxShared title.";
+                    Q_ASSERT(false);
+                    return false;
+                }
+            }
+            else if ( reader.name() == QLatin1String("numFmt") )
+            {
+                //!TODO
+            }
+            else if ( reader.name() == QLatin1String("majorTickMark") )
+            {
+                //!TODO
+            }
+            else if ( reader.name() == QLatin1String("minorTickMark") )
+            {
+                //!TODO
+            }
+            else if ( reader.name() == QLatin1String("tickLblPos") )
+            {
+                //!TODO
+            }
+            else if ( reader.name() == QLatin1String("spPr") )
+            {
+                //!TODO
+            }
+            else if ( reader.name() == QLatin1String("txPr") )
+            {
+                //!TODO
+            }
+            else if ( reader.name() == QLatin1String("crossAx") ) // mandatory element
+            {
+                // dev57
+                uint crossAx = reader.attributes().value(QLatin1String("val")).toUInt(); // for Qt5.1
+                axis->crossAx = crossAx;
+            }
+            else if ( reader.name() == QLatin1String("crosses") )
+            {
+                //!TODO
+            }
+            else if ( reader.name() == QLatin1String("crossesAt") )
+            {
+                //!TODO
+            }
+
+            // reader.readNext();
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name().toString() == name )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisEG_AxShared_Scaling(QXmlStreamReader &reader, XlsxAxis* axis)
+{
+    Q_UNUSED(axis);
+    Q_ASSERT(reader.name() == QLatin1String("scaling"));
+
+    while ( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if ( reader.tokenType() == QXmlStreamReader::StartElement )
+        {
+            if ( reader.name() == QLatin1String("orientation") )
+            {
+            }
+            else
+            {
+            }
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name() == QLatin1String("scaling") )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+/*
+  <xsd:complexType name="CT_Title">
+      <xsd:sequence>
+          <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/>
+          <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
+          <xsd:element name="overlay" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+          <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
+          <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
+          <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+      </xsd:sequence>
+  </xsd:complexType>
+
+<xsd:complexType name="CT_Tx">
+    <xsd:sequence>
+        <xsd:choice minOccurs="1" maxOccurs="1">
+            <xsd:element name="strRef" type="CT_StrRef" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="rich" type="a:CT_TextBody" minOccurs="1" maxOccurs="1"/>
+        </xsd:choice>
+    </xsd:sequence>
+</xsd:complexType>
+
+<xsd:complexType name="CT_StrRef">
+    <xsd:sequence>
+        <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="strCache" type="CT_StrData" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+
+<xsd:complexType name="CT_TextBody">
+    <xsd:sequence>
+        <xsd:element name="bodyPr" type="CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="p" type="CT_TextParagraph" minOccurs="1" maxOccurs="unbounded"/>
+    </xsd:sequence>
+</xsd:complexType>
+  */
+bool ChartPrivate::loadXmlAxisEG_AxShared_Title(QXmlStreamReader &reader, XlsxAxis* axis)
+{
+    Q_ASSERT(reader.name() == QLatin1String("title"));
+
+    while ( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if ( reader.tokenType() == QXmlStreamReader::StartElement )
+        {
+            if ( reader.name() == QLatin1String("tx") )
+            {
+                loadXmlAxisEG_AxShared_Title_Tx(reader, axis);
+            }
+            else if ( reader.name() == QLatin1String("overlay") )
+            {
+                //!TODO: load overlay
+                loadXmlAxisEG_AxShared_Title_Overlay(reader, axis);
+            }
+            else
+            {
+            }
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name() == QLatin1String("title") )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Overlay(QXmlStreamReader &reader, XlsxAxis* axis)
+{
+    Q_UNUSED(axis);
+    Q_ASSERT(reader.name() == QLatin1String("overlay"));
+
+    while ( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if ( reader.tokenType() == QXmlStreamReader::StartElement )
+        {
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name() == QLatin1String("overlay") )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx(QXmlStreamReader &reader, XlsxAxis* axis)
+{
+    Q_ASSERT(reader.name() == QLatin1String("tx"));
+
+    while ( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if ( reader.tokenType() == QXmlStreamReader::StartElement )
+        {
+            if ( reader.name() == QLatin1String("rich") )
+            {
+                loadXmlAxisEG_AxShared_Title_Tx_Rich(reader, axis);
+            }
+            else
+            {
+            }
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name() == QLatin1String("tx") )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx_Rich(QXmlStreamReader &reader, XlsxAxis* axis)
+{
+    Q_ASSERT(reader.name() == QLatin1String("rich"));
+
+    while ( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if ( reader.tokenType() == QXmlStreamReader::StartElement )
+        {
+            if ( reader.name() == QLatin1String("p") )
+            {
+                loadXmlAxisEG_AxShared_Title_Tx_Rich_P(reader, axis);
+            }
+            else
+            {
+            }
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name() == QLatin1String("rich") )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx_Rich_P(QXmlStreamReader &reader, XlsxAxis* axis)
+{
+    Q_ASSERT(reader.name() == QLatin1String("p"));
+
+    while ( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if ( reader.tokenType() == QXmlStreamReader::StartElement )
+        {
+            if ( reader.name() == QLatin1String("r") )
+            {
+                loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(reader, axis);
+            }
+            else if ( reader.name() == QLatin1String("pPr") )
+            {
+                loadXmlAxisEG_AxShared_Title_Tx_Rich_P_pPr(reader, axis);
+            }
+            else
+            {
+
+            }
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name() == QLatin1String("p") )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx_Rich_P_pPr(QXmlStreamReader &reader, XlsxAxis* axis)
+{
+    Q_UNUSED(axis);
+    Q_ASSERT(reader.name() == QLatin1String("pPr"));
+
+    while ( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if ( reader.tokenType() == QXmlStreamReader::StartElement )
+        {
+            if ( reader.name() == QLatin1String("defRPr") )
+            {
+                reader.readElementText();
+            }
+            else
+            {
+            }
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name() == QLatin1String("pPr") )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(QXmlStreamReader &reader, XlsxAxis* axis)
+{
+    Q_ASSERT(reader.name() == QLatin1String("r"));
+
+    while ( !reader.atEnd() )
+    {
+        reader.readNextStartElement();
+        if ( reader.tokenType() == QXmlStreamReader::StartElement )
+        {
+            if ( reader.name() == QLatin1String("t") )
+            {
+                QString strAxisName = reader.readElementText();
+                XlsxAxis::AxisPos axisPos = axis->axisPos;
+                axis->axisNames[ axisPos ] = strAxisName;
+            }
+            else
+            {
+            }
+        }
+        else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
+                  reader.name() == QLatin1String("r") )
+        {
+            break;
+        }
+    }
+
+    return true;
+}
+
+/*
+<xsd:complexType name="CT_PlotArea">
+    <xsd:sequence>
+        <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
+        <xsd:choice minOccurs="1" maxOccurs="unbounded">
+            <xsd:element name="areaChart" type="CT_AreaChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="area3DChart" type="CT_Area3DChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="lineChart" type="CT_LineChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="line3DChart" type="CT_Line3DChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="stockChart" type="CT_StockChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="radarChart" type="CT_RadarChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="scatterChart" type="CT_ScatterChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="pieChart" type="CT_PieChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="pie3DChart" type="CT_Pie3DChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="doughnutChart" type="CT_DoughnutChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="barChart" type="CT_BarChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="bar3DChart" type="CT_Bar3DChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="ofPieChart" type="CT_OfPieChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="surfaceChart" type="CT_SurfaceChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="surface3DChart" type="CT_Surface3DChart" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="bubbleChart" type="CT_BubbleChart" minOccurs="1" maxOccurs="1"/>
+        </xsd:choice>
+        <xsd:choice minOccurs="0" maxOccurs="unbounded">
+            <xsd:element name="valAx" type="CT_ValAx" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="catAx" type="CT_CatAx" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="dateAx" type="CT_DateAx" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="serAx" type="CT_SerAx" minOccurs="1" maxOccurs="1"/>
+        </xsd:choice>
+        <xsd:element name="dTable" type="CT_DTable" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+*/
+
+/*
+<xsd:complexType name="CT_CatAx">
+    <xsd:sequence>
+        <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="lblAlgn" type="CT_LblAlgn" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="noMultiLvlLbl" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+<!----------------------------------------------------------------------------->
+<xsd:complexType name="CT_DateAx">
+    <xsd:sequence>
+        <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="majorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="minorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+<!----------------------------------------------------------------------------->
+<xsd:complexType name="CT_SerAx">
+    <xsd:sequence>
+    <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+<!----------------------------------------------------------------------------->
+<xsd:complexType name="CT_ValAx">
+    <xsd:sequence>
+        <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="crossBetween" type="CT_CrossBetween" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="dispUnits" type="CT_DispUnits" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+*/
+
+void ChartPrivate::saveXmlAxis(QXmlStreamWriter &writer) const
+{
+    for ( int i = 0 ; i < axisList.size() ; ++i )
+    {
+        XlsxAxis* axis = axisList[i].get();
+        if ( nullptr == axis )
+            continue;
+
+        if ( axis->type == XlsxAxis::T_Cat  ) { saveXmlAxisCatAx( writer, axis ); }
+        if ( axis->type == XlsxAxis::T_Val  ) { saveXmlAxisValAx( writer, axis ); }
+        if ( axis->type == XlsxAxis::T_Ser  ) { saveXmlAxisSerAx( writer, axis ); }
+        if ( axis->type == XlsxAxis::T_Date ) { saveXmlAxisDateAx( writer, axis ); }
+    }
+
+}
+
+void ChartPrivate::saveXmlAxisCatAx(QXmlStreamWriter &writer, XlsxAxis* axis) const
+{
+/*
+<xsd:complexType name="CT_CatAx">
+    <xsd:sequence>
+        <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="lblAlgn" type="CT_LblAlgn" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="noMultiLvlLbl" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+*/
+
+    writer.writeStartElement(QStringLiteral("c:catAx"));
+
+    saveXmlAxisEG_AxShared(writer, axis); // EG_AxShared
+
+    //!TODO: write element
+    // auto
+    // lblAlgn
+    // lblOffset
+    // tickLblSkip
+    // tickMarkSkip
+    // noMultiLvlLbl
+    // extLst
+
+    writer.writeEndElement(); // c:catAx
+}
+
+void ChartPrivate::saveXmlAxisDateAx(QXmlStreamWriter &writer, XlsxAxis* axis) const
+{
+/*
+<xsd:complexType name="CT_DateAx">
+    <xsd:sequence>
+        <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="majorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="minorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+*/
+
+    writer.writeStartElement(QStringLiteral("c:dateAx"));
+
+    saveXmlAxisEG_AxShared(writer, axis); // EG_AxShared
+
+    //!TODO: write element
+    // auto
+    // lblOffset
+    // baseTimeUnit
+    // majorUnit
+    // majorTimeUnit
+    // minorUnit
+    // minorTimeUnit
+    // extLst
+
+    writer.writeEndElement(); // c:dateAx
+}
+
+void ChartPrivate::saveXmlAxisSerAx(QXmlStreamWriter &writer, XlsxAxis* axis) const
+{
+/*
+<xsd:complexType name="CT_SerAx">
+    <xsd:sequence>
+    <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+*/
+
+    writer.writeStartElement(QStringLiteral("c:serAx"));
+
+    saveXmlAxisEG_AxShared(writer, axis); // EG_AxShared
+
+    //!TODO: write element
+    // tickLblSkip
+    // tickMarkSkip
+    // extLst
+
+    writer.writeEndElement(); // c:serAx
+}
+
+void ChartPrivate::saveXmlAxisValAx(QXmlStreamWriter &writer, XlsxAxis* axis) const
+{
+/*
+<xsd:complexType name="CT_ValAx">
+    <xsd:sequence>
+        <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="crossBetween" type="CT_CrossBetween" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="dispUnits" type="CT_DispUnits" minOccurs="0" maxOccurs="1"/>
+        <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+    </xsd:sequence>
+</xsd:complexType>
+*/
+
+    writer.writeStartElement(QStringLiteral("c:valAx"));
+
+    saveXmlAxisEG_AxShared(writer, axis); // EG_AxShared
+
+    //!TODO: write element
+    // crossBetween
+    // majorUnit
+    // minorUnit
+    // dispUnits
+    // extLst
+
+    writer.writeEndElement(); // c:valAx
+}
+
+void ChartPrivate::saveXmlAxisEG_AxShared(QXmlStreamWriter &writer, XlsxAxis* axis) const
+{
+    /*
+    <xsd:group name="EG_AxShared">
+        <xsd:sequence>
+            <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> (*)
+            <xsd:element name="scaling" type="CT_Scaling" minOccurs="1" maxOccurs="1"/> (*)
+            <xsd:element name="delete" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="axPos" type="CT_AxPos" minOccurs="1" maxOccurs="1"/> (*)
+            <xsd:element name="majorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="minorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="title" type="CT_Title" minOccurs="0" maxOccurs="1"/> (***********************)
+            <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="majorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="minorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="tickLblPos" type="CT_TickLblPos" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="crossAx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> (*)
+            <xsd:choice minOccurs="0" maxOccurs="1">
+                <xsd:element name="crosses" type="CT_Crosses" minOccurs="1" maxOccurs="1"/>
+                <xsd:element name="crossesAt" type="CT_Double" minOccurs="1" maxOccurs="1"/>
+            </xsd:choice>
+        </xsd:sequence>
+    </xsd:group>
+    */
+
+    writer.writeEmptyElement(QStringLiteral("c:axId")); // 21.2.2.9. axId (Axis ID) (mandatory value)
+        writer.writeAttribute(QStringLiteral("val"), QString::number(axis->axisId));
+
+    writer.writeStartElement(QStringLiteral("c:scaling")); // CT_Scaling (mandatory value)
+        writer.writeEmptyElement(QStringLiteral("c:orientation")); // CT_Orientation
+            writer.writeAttribute(QStringLiteral("val"), QStringLiteral("minMax")); // ST_Orientation
+    writer.writeEndElement(); // c:scaling
+
+    writer.writeEmptyElement(QStringLiteral("c:axPos")); // axPos CT_AxPos (mandatory value)
+        QString pos = GetAxisPosString( axis->axisPos );
+        if ( !pos.isEmpty() )
+        {
+            writer.writeAttribute(QStringLiteral("val"), pos); // ST_AxPos
+        }
+
+    if( majorGridlinesEnabled )
+    {
+        writer.writeEmptyElement(QStringLiteral("c:majorGridlines"));
+    }
+    if( minorGridlinesEnabled )
+    {
+        writer.writeEmptyElement(QStringLiteral("c:minorGridlines"));
+    }
+
+    saveXmlAxisEG_AxShared_Title(writer, axis); // "c:title" CT_Title
+
+    writer.writeEmptyElement(QStringLiteral("c:crossAx")); // crossAx (mandatory value)
+        writer.writeAttribute(QStringLiteral("val"), QString::number(axis->crossAx));
+
+}
+
+void ChartPrivate::saveXmlAxisEG_AxShared_Title(QXmlStreamWriter &writer, XlsxAxis* axis) const
+{
+    // CT_Title
+
+    /*
+    <xsd:complexType name="CT_Title">
+        <xsd:sequence>
+            <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="overlay" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+        </xsd:sequence>
+    </xsd:complexType>
+    */
+    /*
+    <xsd:complexType name="CT_Tx">
+        <xsd:sequence>
+            <xsd:choice minOccurs="1" maxOccurs="1">
+                <xsd:element name="strRef" type="CT_StrRef" minOccurs="1" maxOccurs="1"/>
+                <xsd:element name="rich" type="a:CT_TextBody" minOccurs="1" maxOccurs="1"/>
+            </xsd:choice>
+        </xsd:sequence>
+    </xsd:complexType>
+    */
+    /*
+    <xsd:complexType name="CT_StrRef">
+        <xsd:sequence>
+            <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="strCache" type="CT_StrData" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
+        </xsd:sequence>
+    </xsd:complexType>
+    */
+    /*
+    <xsd:complexType name="CT_TextBody">
+        <xsd:sequence>
+            <xsd:element name="bodyPr" type="CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="p" type="CT_TextParagraph" minOccurs="1" maxOccurs="unbounded"/>
+        </xsd:sequence>
+    </xsd:complexType>
+    */
+
+    writer.writeStartElement(QStringLiteral("c:title"));
+
+    // CT_Tx {{
+     writer.writeStartElement(QStringLiteral("c:tx"));
+
+      writer.writeStartElement(QStringLiteral("c:rich")); // CT_TextBody
+
+       writer.writeEmptyElement(QStringLiteral("a:bodyPr")); // CT_TextBodyProperties
+
+       writer.writeEmptyElement(QStringLiteral("a:lstStyle")); // CT_TextListStyle
+
+       writer.writeStartElement(QStringLiteral("a:p"));
+
+        writer.writeStartElement(QStringLiteral("a:pPr"));
+            writer.writeAttribute(QStringLiteral("lvl"), QString::number(0));
+
+            writer.writeStartElement(QStringLiteral("a:defRPr"));
+            writer.writeAttribute(QStringLiteral("b"), QString::number(0));
+            writer.writeEndElement(); // a:defRPr
+        writer.writeEndElement(); // a:pPr
+
+        writer.writeStartElement(QStringLiteral("a:r"));
+        QString strAxisName = GetAxisName(axis);
+        writer.writeTextElement( QStringLiteral("a:t"), strAxisName );
+        writer.writeEndElement(); // a:r
+
+       writer.writeEndElement(); // a:p
+
+      writer.writeEndElement(); // c:rich
+
+     writer.writeEndElement(); // c:tx
+     // CT_Tx }}
+
+     writer.writeStartElement(QStringLiteral("c:overlay"));
+        writer.writeAttribute(QStringLiteral("val"), QString::number(0)); // CT_Boolean
+     writer.writeEndElement(); // c:overlay
+
+    writer.writeEndElement(); // c:title
+
+}
+
+QString ChartPrivate::GetAxisPosString( XlsxAxis::AxisPos axisPos ) const
+{
+    QString pos;
+    switch ( axisPos )
+    {
+        case XlsxAxis::Top    : pos = QStringLiteral("t"); break;
+        case XlsxAxis::Bottom : pos = QStringLiteral("b"); break;
+        case XlsxAxis::Left   : pos = QStringLiteral("l"); break;
+        case XlsxAxis::Right  : pos = QStringLiteral("r"); break;
+        default: break; // ??
+    }
+
+    return pos;
+}
+
+QString ChartPrivate::GetAxisName(XlsxAxis* axis) const
+{
+    QString strAxisName;
+    if ( NULL == axis )
+        return strAxisName;
+
+    QString pos = GetAxisPosString( axis->axisPos ); // l, t, r, b
+    if ( pos.isEmpty() )
+        return strAxisName;
+
+    strAxisName = axis->axisNames[ axis->axisPos ];
+    return strAxisName;
+}
+
+
+///
+/// \brief ChartPrivate::readSubTree
+/// \param reader
+/// \return
+///
+QString ChartPrivate::readSubTree(QXmlStreamReader &reader)
+{
+    QString treeString;
+    QString prefix;
+    const auto& treeName = reader.name();
+
+    while (!reader.atEnd())
+    {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            prefix = reader.prefix().toString();
+
+            treeString += QLatin1String("<") + reader.qualifiedName().toString();
+
+            const QXmlStreamAttributes attributes = reader.attributes();
+            for (const QXmlStreamAttribute &attr : attributes) {
+                treeString += QLatin1String(" ") + attr.name().toString() + QLatin1String("=\"") + attr.value().toString() + QLatin1String("\"");
+            }
+            treeString += QStringLiteral(">");
+        }
+        else if (reader.tokenType() == QXmlStreamReader::EndElement )
+        {
+            if( reader.name() == treeName)
+            {
+                break;
+            }
+            treeString += QLatin1String("</") + reader.qualifiedName().toString() + QLatin1String(">");
+        }
+    }
+
+    return treeString;
+}
+
+
+///
+/// \brief ChartPrivate::loadXmlChartLegend
+/// \param reader
+/// \return
+///
+bool ChartPrivate::loadXmlChartLegend(QXmlStreamReader &reader)
+{
+
+    Q_ASSERT(reader.name() == QLatin1String("legend"));
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("legend")))
+    {
+        if (reader.readNextStartElement())
+        {
+            if (reader.name() == QLatin1String("legendPos")) // c:legendPos
+            {
+                QString pos = reader.attributes().value(QLatin1String("val")).toString();
+                if( pos.compare(QLatin1String("r"), Qt::CaseInsensitive) == 0)
+                {
+                    // legendPos = Chart::ChartAxisPos::Right;
+                    legendPos = Chart::Right;
+                }
+                else
+                if( pos.compare(QLatin1String("l"), Qt::CaseInsensitive) == 0)
+                {
+                    // legendPos = Chart::ChartAxisPos::Left;
+                    legendPos = Chart::Left;
+                }
+                else
+                if( pos.compare(QLatin1String("t"), Qt::CaseInsensitive) == 0)
+                {
+                    // legendPos = Chart::ChartAxisPos::Top;
+                    legendPos = Chart::Top;
+                }
+                else
+                if( pos.compare(QLatin1String("b"), Qt::CaseInsensitive) == 0)
+                {
+                    // legendPos = Chart::ChartAxisPos::Bottom;
+                    legendPos = Chart::Bottom;
+                }
+                else
+                {
+                    // legendPos = Chart::ChartAxisPos::None;
+                    legendPos = Chart::None;
+                }
+            }
+            else
+            if (reader.name() == QLatin1String("overlay")) // c:legendPos
+            {
+                QString pos = reader.attributes().value(QLatin1String("val")).toString();
+                if( pos.compare(QLatin1String("1"), Qt::CaseInsensitive) == 0 )
+                {
+                    legendOverlay = true;
+                }
+                else
+                {
+                    legendOverlay = false;
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxchartsheet.cpp b/internal_system_v1/QXlsx/source/xlsxchartsheet.cpp
new file mode 100644
index 0000000..12fdd79
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxchartsheet.cpp
@@ -0,0 +1,142 @@
+// xlsxchartsheet.cpp
+
+#include <QtGlobal>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+#include <QDir>
+
+#include "xlsxchartsheet.h"
+#include "xlsxchartsheet_p.h"
+#include "xlsxworkbook.h"
+#include "xlsxutility_p.h"
+#include "xlsxdrawing_p.h"
+#include "xlsxdrawinganchor_p.h"
+#include "xlsxchart.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+ChartsheetPrivate::ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag)
+    : AbstractSheetPrivate(p, flag), chart(0)
+{
+
+}
+
+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);
+
+        DrawingAbsoluteAnchor *anchor = new DrawingAbsoluteAnchor(drawing(), DrawingAnchor::Picture);
+
+        anchor->pos = QPoint(0, 0);
+        anchor->ext = QSize(9293679, 6068786);
+
+        QSharedPointer<Chart> chart = QSharedPointer<Chart>(new Chart(this, flag));
+        chart->setChartType(Chart::CT_BarChart);
+        anchor->setObjectGraphicFrame(chart);
+
+        d_func()->chart = chart.data();
+    }
+}
+
+/*!
+ * \internal
+ *
+ * Make a copy of this sheet.
+ */
+
+Chartsheet *Chartsheet::copy(const QString &distName, int distId) const
+{
+    //:Todo
+    Q_UNUSED(distName)
+    Q_UNUSED(distId)
+    return 0;
+}
+
+/*!
+ * 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
diff --git a/internal_system_v1/QXlsx/source/xlsxcolor.cpp b/internal_system_v1/QXlsx/source/xlsxcolor.cpp
new file mode 100644
index 0000000..84512b6
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxcolor.cpp
@@ -0,0 +1,196 @@
+// xlsxcolor.cpp
+
+#include <QDataStream>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+#include <QDebug>
+
+#include "xlsxcolor_p.h"
+#include "xlsxstyles_p.h"
+#include "xlsxutility_p.h"
+
+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)
+{
+    QColor color;
+    if (c.startsWith(u'#')) {
+        color.setNamedColor(c);
+    } else {
+        color.setNamedColor(QLatin1Char('#') + c);
+    }
+    return color;
+}
+
+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
diff --git a/internal_system_v1/QXlsx/source/xlsxconditionalformatting.cpp b/internal_system_v1/QXlsx/source/xlsxconditionalformatting.cpp
new file mode 100644
index 0000000..510cc2c
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxconditionalformatting.cpp
@@ -0,0 +1,751 @@
+// xlsxconditionalformatting.cpp
+
+#include <QtGlobal>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+#include <QDebug>
+
+#include "xlsxconditionalformatting.h"
+#include "xlsxconditionalformatting_p.h"
+#include "xlsxworksheet.h"
+#include "xlsxcellrange.h"
+#include "xlsxstyles_p.h"
+
+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)
+{
+    this->d = other.d;
+    return *this;
+}
+
+
+/*!
+ * Destroy the object.
+ */
+ConditionalFormatting::~ConditionalFormatting()
+{
+}
+
+/*!
+ * Add a hightlight 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 hightlight 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 hightlight 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 if ((it = rule->attrs.constFind(XlsxCfRuleData::A_formula1)) != 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
diff --git a/internal_system_v1/QXlsx/source/xlsxcontenttypes.cpp b/internal_system_v1/QXlsx/source/xlsxcontenttypes.cpp
new file mode 100644
index 0000000..e3dd167
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxcontenttypes.cpp
@@ -0,0 +1,184 @@
+// xlsxcontenttypes.cpp
+
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QFile>
+#include <QMapIterator>
+#include <QBuffer>
+#include <QDebug>
+
+#include "xlsxcontenttypes_p.h"
+
+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
diff --git a/internal_system_v1/QXlsx/source/xlsxdatavalidation.cpp b/internal_system_v1/QXlsx/source/xlsxdatavalidation.cpp
new file mode 100644
index 0000000..cf4c8e4
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxdatavalidation.cpp
@@ -0,0 +1,537 @@
+// xlsxdatavalidation.cpp
+
+#include <QtGlobal>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+#include "xlsxdatavalidation.h"
+#include "xlsxdatavalidation_p.h"
+#include "xlsxworksheet.h"
+#include "xlsxcellrange.h"
+
+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)
+{
+    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/disabe blank allow based on \a enable.
+ */
+void DataValidation::setAllowBlank(bool enable)
+{
+    d->allowBlank = enable;
+}
+
+/*!
+    Enable/disabe prompt message visible based on \a visible.
+ */
+void DataValidation::setPromptMessageVisible(bool visible)
+{
+    d->isPromptMessageVisible = visible;
+}
+
+/*!
+    Enable/disabe 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
diff --git a/internal_system_v1/QXlsx/source/xlsxdatetype.cpp b/internal_system_v1/QXlsx/source/xlsxdatetype.cpp
new file mode 100644
index 0000000..6486b6a
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxdatetype.cpp
@@ -0,0 +1,85 @@
+// xlsxdatetype.cpp
+
+#include <QtGlobal>
+
+#include "xlsxglobal.h"
+#include "xlsxutility_p.h"
+#include "xlsxdatetype.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
diff --git a/internal_system_v1/QXlsx/source/xlsxdocpropsapp.cpp b/internal_system_v1/QXlsx/source/xlsxdocpropsapp.cpp
new file mode 100644
index 0000000..01d40a1
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxdocpropsapp.cpp
@@ -0,0 +1,138 @@
+// xlsxdocpropsapp.cpp
+
+#include "xlsxdocpropsapp_p.h"
+
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QDir>
+#include <QFile>
+#include <QDateTime>
+#include <QVariant>
+#include <QBuffer>
+
+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
diff --git a/internal_system_v1/QXlsx/source/xlsxdocpropscore.cpp b/internal_system_v1/QXlsx/source/xlsxdocpropscore.cpp
new file mode 100644
index 0000000..b11c8b6
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxdocpropscore.cpp
@@ -0,0 +1,176 @@
+// xlsxdocpropscore.cpp
+
+#include <QtGlobal>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QDir>
+#include <QFile>
+#include <QDateTime>
+#include <QDebug>
+#include <QBuffer>
+
+#include "xlsxdocpropscore_p.h"
+
+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
diff --git a/internal_system_v1/QXlsx/source/xlsxdocument.cpp b/internal_system_v1/QXlsx/source/xlsxdocument.cpp
new file mode 100644
index 0000000..cf6d898
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxdocument.cpp
@@ -0,0 +1,1454 @@
+// xlsxdocument.cpp
+
+#include <QtGlobal>
+#include <QFile>
+#include <QPointF>
+#include <QBuffer>
+#include <QDir>
+#include <QTemporaryFile>
+#include <QFile>
+#include <QSharedPointer>
+#include <QDebug>
+
+#include "xlsxdocument.h"
+#include "xlsxdocument_p.h"
+#include "xlsxworkbook.h"
+#include "xlsxworksheet.h"
+#include "xlsxcontenttypes_p.h"
+#include "xlsxrelationships_p.h"
+#include "xlsxstyles_p.h"
+#include "xlsxtheme_p.h"
+#include "xlsxdocpropsapp_p.h"
+#include "xlsxdocpropscore_p.h"
+#include "xlsxsharedstrings_p.h"
+#include "xlsxutility_p.h"
+#include "xlsxworkbook_p.h"
+#include "xlsxdrawing_p.h"
+#include "xlsxmediafile_p.h"
+#include "xlsxchart.h"
+#include "xlsxzipreader_p.h"
+#include "xlsxzipwriter_p.h"
+
+/*
+	From Wikipedia: The Open Packaging Conventions (OPC) is a
+	container-file technology initially created by Microsoft to store
+	a combination of XML and non-XML files that together form a single
+	entity such as an Open XML Paper Specification (OpenXPS)
+	document. http://en.wikipedia.org/wiki/Open_Packaging_Conventions.
+
+	At its simplest an Excel XLSX file contains the following elements:
+
+		 ____ [Content_Types].xml
+		|
+		|____ docProps
+		| |____ app.xml
+		| |____ core.xml
+		|
+		|____ xl
+		| |____ workbook.xml
+		| |____ worksheets
+		| | |____ sheet1.xml
+		| |
+		| |____ styles.xml
+		| |
+		| |____ theme
+		| | |____ theme1.xml
+		| |
+		| |_____rels
+		| |____ workbook.xml.rels
+		|
+		|_____rels
+		  |____ .rels
+
+	The Packager class coordinates the classes that represent the
+	elements of the package and writes them into the XLSX file.
+*/
+
+QT_BEGIN_NAMESPACE_XLSX
+
+namespace xlsxDocumentCpp {
+	std::string copyTag(const std::string &sFrom, const std::string &sTo, const std::string &tag) {
+		const std::string tagToFindStart = "<" + tag;
+		const std::string tagToFindEnd = "</" + tag;
+		const std::string tagEnd = "</" + tag + ">";
+
+		// search all occurrences of tag in 'sFrom'
+		std::string sFromData = "";
+		size_t startIndex = 0;
+		while (true) {
+			std::size_t startPos = sFrom.find(tagToFindStart, startIndex);
+			if (startPos != std::string::npos) {
+				std::size_t endPos = sFrom.find(tagToFindEnd, startPos);
+				std::string tagEndTmp = tagEnd;
+				if (endPos == std::string::npos) {	// second try to find the ending, maybe it is "/>" 
+					endPos = sFrom.find("/>", startPos);
+					tagEndTmp = "/>";
+				}
+				if (endPos != std::string::npos) {
+					sFromData += sFrom.substr(startPos, endPos - startPos) + tagEndTmp;
+					startIndex = endPos + strlen(tagEndTmp.c_str());
+				}
+				else {
+					break;
+				}
+			}
+			else {
+				break;
+			}
+		}
+
+		std::string sOut = sTo; // copy 'sTo' in the output string
+
+		if (!sFromData.empty()) { // tag found in 'from'?
+								  // search all occurrences of tag in 'sOut' and delete them
+			int firstPosTag = -1;
+			while (true) {
+				std::size_t startPos = sOut.find(tagToFindStart);
+				if (startPos != std::string::npos) {
+					std::size_t endPos = sOut.find(tagToFindEnd);
+					std::string tagEndTmp = tagEnd;
+					if (endPos == std::string::npos) {	// second try to find the ending, maybe it is "/>" 
+						endPos = sOut.find("/>", startPos);
+						tagEndTmp = "/>";
+					}
+					if (endPos != std::string::npos) {
+						if (firstPosTag < 0)
+							firstPosTag = startPos;
+						std::string stringBefore = sOut.substr(0, startPos);
+						endPos += strlen(tagEndTmp.c_str());
+						std::string stringAfter = sOut.substr(endPos, strlen(sOut.c_str()) - endPos);
+						sOut = stringBefore + stringAfter;
+					}
+					else {
+						break;
+					}
+				}
+				else {
+					break;
+				}
+			}
+
+			if (firstPosTag == -1) {
+				// tag not found in 'sTo' file
+				// try to find a default pos using standard tags
+				std::vector<std::string> defaultPos{ "</styleSheet>", "<pageMargins", "</workbook>" };
+				for (unsigned int i = 0; i < defaultPos.size(); ++i) {
+					std::size_t iDefaultPos = sOut.find(defaultPos[i]);
+					if (iDefaultPos != std::string::npos) {
+						firstPosTag = iDefaultPos;
+						break;
+					}
+				}
+			}
+
+			// add the tag extracted from 'sFrom' in 'sOut'
+			// add in the position of the first tag found in 'sOut' ('firstPosTag')
+			if (firstPosTag >= 0) {
+				std::string stringBefore = sOut.substr(0, firstPosTag);
+				std::string stringAfter = sOut.substr(firstPosTag, strlen(sOut.c_str()) - firstPosTag);
+				sOut = stringBefore + sFromData + stringAfter;
+			}
+		}
+
+		return sOut;
+	}
+}
+
+DocumentPrivate::DocumentPrivate(Document *p) :
+	q_ptr(p), defaultPackageName(QStringLiteral("Book1.xlsx")),
+	isLoad(false)
+{
+}
+
+void DocumentPrivate::init()
+{
+    if (!contentTypes)
+        contentTypes = std::make_shared<ContentTypes>(ContentTypes::F_NewFromScratch);
+
+    if (workbook.isNull())
+        workbook = QSharedPointer<Workbook>(new Workbook(Workbook::F_NewFromScratch));
+}
+
+bool DocumentPrivate::loadPackage(QIODevice *device)
+{
+	Q_Q(Document);
+	ZipReader zipReader(device);
+	QStringList filePaths = zipReader.filePaths();
+
+	//Load the Content_Types file
+	if (!filePaths.contains(QLatin1String("[Content_Types].xml")))
+		return false;
+    contentTypes = std::make_shared<ContentTypes>(ContentTypes::F_LoadFromExists);
+	contentTypes->loadFromXmlData(zipReader.fileData(QStringLiteral("[Content_Types].xml")));
+
+	//Load root rels file
+	if (!filePaths.contains(QLatin1String("_rels/.rels")))
+		return false;
+	Relationships rootRels;
+	rootRels.loadFromXmlData(zipReader.fileData(QStringLiteral("_rels/.rels")));
+
+	//load core property
+	QList<XlsxRelationship> rels_core = rootRels.packageRelationships(QStringLiteral("/metadata/core-properties"));
+	if (!rels_core.isEmpty()) {
+		//Get the core property file name if it exists.
+		//In normal case, this should be "docProps/core.xml"
+		QString docPropsCore_Name = rels_core[0].target;
+
+		DocPropsCore props(DocPropsCore::F_LoadFromExists);
+		props.loadFromXmlData(zipReader.fileData(docPropsCore_Name));
+        const auto propNames = props.propertyNames();
+        for (const QString &name : propNames)
+			q->setDocumentProperty(name, props.property(name));
+	}
+
+	//load app property
+	QList<XlsxRelationship> rels_app = rootRels.documentRelationships(QStringLiteral("/extended-properties"));
+	if (!rels_app.isEmpty()) {
+		//Get the app property file name if it exists.
+		//In normal case, this should be "docProps/app.xml"
+		QString docPropsApp_Name = rels_app[0].target;
+
+		DocPropsApp props(DocPropsApp::F_LoadFromExists);
+		props.loadFromXmlData(zipReader.fileData(docPropsApp_Name));
+        const auto propNames = props.propertyNames();
+        for (const QString &name : propNames)
+			q->setDocumentProperty(name, props.property(name));
+	}
+
+	//load workbook now, Get the workbook file path from the root rels file
+	//In normal case, this should be "xl/workbook.xml"
+    workbook = QSharedPointer<Workbook>(new Workbook(Workbook::F_LoadFromExists));
+	QList<XlsxRelationship> rels_xl = rootRels.documentRelationships(QStringLiteral("/officeDocument"));
+	if (rels_xl.isEmpty())
+		return false;
+    const QString xlworkbook_Path = rels_xl[0].target;
+    const auto parts = splitPath(xlworkbook_Path);
+    const QString xlworkbook_Dir = parts.first();
+    const QString relFilePath = getRelFilePath(xlworkbook_Path);
+
+    workbook->relationships()->loadFromXmlData( zipReader.fileData(relFilePath) );
+	workbook->setFilePath(xlworkbook_Path);
+	workbook->loadFromXmlData(zipReader.fileData(xlworkbook_Path));
+
+	//load styles
+	QList<XlsxRelationship> rels_styles = workbook->relationships()->documentRelationships(QStringLiteral("/styles"));
+	if (!rels_styles.isEmpty()) {
+		//In normal case this should be styles.xml which in xl
+		QString name = rels_styles[0].target;
+
+        // dev34
+        QString path;
+        if ( xlworkbook_Dir == QLatin1String(".") ) // root
+        {
+            path = name;
+        }
+        else
+        {
+            path = xlworkbook_Dir + QLatin1String("/") + name;
+        }
+
+		QSharedPointer<Styles> styles (new Styles(Styles::F_LoadFromExists));
+		styles->loadFromXmlData(zipReader.fileData(path));
+		workbook->d_func()->styles = styles;
+	}
+
+	//load sharedStrings
+	QList<XlsxRelationship> rels_sharedStrings = workbook->relationships()->documentRelationships(QStringLiteral("/sharedStrings"));
+	if (!rels_sharedStrings.isEmpty()) {
+		//In normal case this should be sharedStrings.xml which in xl
+		QString name = rels_sharedStrings[0].target;
+		QString path = xlworkbook_Dir + QLatin1String("/") + name;
+		workbook->d_func()->sharedStrings->loadFromXmlData(zipReader.fileData(path));
+	}
+
+	//load theme
+	QList<XlsxRelationship> rels_theme = workbook->relationships()->documentRelationships(QStringLiteral("/theme"));
+	if (!rels_theme.isEmpty()) {
+		//In normal case this should be theme/theme1.xml which in xl
+		QString name = rels_theme[0].target;
+		QString path = xlworkbook_Dir + QLatin1String("/") + name;
+		workbook->theme()->loadFromXmlData(zipReader.fileData(path));
+	}
+
+	//load sheets
+	for (int i=0; i<workbook->sheetCount(); ++i) {
+		AbstractSheet *sheet = workbook->sheet(i);
+        QString strFilePath = sheet->filePath();
+        QString rel_path = getRelFilePath(strFilePath);
+		//If the .rel file exists, load it.
+		if (zipReader.filePaths().contains(rel_path))
+			sheet->relationships()->loadFromXmlData(zipReader.fileData(rel_path));
+		sheet->loadFromXmlData(zipReader.fileData(sheet->filePath()));
+	}
+
+	//load external links
+	for (int i=0; i<workbook->d_func()->externalLinks.count(); ++i) {
+		SimpleOOXmlFile *link = workbook->d_func()->externalLinks[i].data();
+		QString rel_path = getRelFilePath(link->filePath());
+		//If the .rel file exists, load it.
+		if (zipReader.filePaths().contains(rel_path))
+			link->relationships()->loadFromXmlData(zipReader.fileData(rel_path));
+		link->loadFromXmlData(zipReader.fileData(link->filePath()));
+	}
+
+	//load drawings
+	for (int i=0; i<workbook->drawings().size(); ++i) {
+		Drawing *drawing = workbook->drawings()[i];
+		QString rel_path = getRelFilePath(drawing->filePath());
+		if (zipReader.filePaths().contains(rel_path))
+			drawing->relationships()->loadFromXmlData(zipReader.fileData(rel_path));
+		drawing->loadFromXmlData(zipReader.fileData(drawing->filePath()));
+	}
+
+	//load charts
+	QList<QSharedPointer<Chart> > chartFileToLoad = workbook->chartFiles();
+	for (int i=0; i<chartFileToLoad.size(); ++i) {
+		QSharedPointer<Chart> cf = chartFileToLoad[i];
+		cf->loadFromXmlData(zipReader.fileData(cf->filePath()));
+	}
+
+	//load media files
+    const auto mediaFileToLoad = workbook->mediaFiles();
+    for (const auto &mf : mediaFileToLoad) {
+		const QString path = mf->fileName();
+		const QString suffix = path.mid(path.lastIndexOf(QLatin1Char('.'))+1);
+		mf->set(zipReader.fileData(path), suffix);
+	}
+
+	isLoad = true; 
+	return true;
+}
+
+bool DocumentPrivate::savePackage(QIODevice *device) const
+{
+	Q_Q(const Document);
+
+	ZipWriter zipWriter(device);
+	if (zipWriter.error())
+		return false;
+
+	contentTypes->clearOverrides();
+
+	DocPropsApp docPropsApp(DocPropsApp::F_NewFromScratch);
+	DocPropsCore docPropsCore(DocPropsCore::F_NewFromScratch);
+
+	// save worksheet xml files
+	QList<QSharedPointer<AbstractSheet> > worksheets = workbook->getSheetsByTypes(AbstractSheet::ST_WorkSheet);
+	if (!worksheets.isEmpty())
+		docPropsApp.addHeadingPair(QStringLiteral("Worksheets"), worksheets.size());
+
+    for (int i = 0 ; i < worksheets.size(); ++i)
+    {
+		QSharedPointer<AbstractSheet> sheet = worksheets[i];
+        contentTypes->addWorksheetName(QStringLiteral("sheet%1").arg(i+1));
+		docPropsApp.addPartTitle(sheet->sheetName());
+
+        zipWriter.addFile(QStringLiteral("xl/worksheets/sheet%1.xml").arg(i+1), sheet->saveToXmlData());
+
+		Relationships *rel = sheet->relationships();
+		if (!rel->isEmpty())
+            zipWriter.addFile(QStringLiteral("xl/worksheets/_rels/sheet%1.xml.rels").arg(i+1), rel->saveToXmlData());
+	}
+
+	//save chartsheet xml files
+	QList<QSharedPointer<AbstractSheet> > chartsheets = workbook->getSheetsByTypes(AbstractSheet::ST_ChartSheet);
+	if (!chartsheets.isEmpty())
+        docPropsApp.addHeadingPair(QStringLiteral("Chartsheets"), chartsheets.size());
+    for (int i=0; i<chartsheets.size(); ++i)
+    {
+		QSharedPointer<AbstractSheet> sheet = chartsheets[i];
+        contentTypes->addWorksheetName(QStringLiteral("sheet%1").arg(i+1));
+		docPropsApp.addPartTitle(sheet->sheetName());
+
+        zipWriter.addFile(QStringLiteral("xl/chartsheets/sheet%1.xml").arg(i+1), sheet->saveToXmlData());
+		Relationships *rel = sheet->relationships();
+		if (!rel->isEmpty())
+            zipWriter.addFile(QStringLiteral("xl/chartsheets/_rels/sheet%1.xml.rels").arg(i+1), rel->saveToXmlData());
+	}
+
+	// save external links xml files
+    for (int i=0; i<workbook->d_func()->externalLinks.count(); ++i)
+    {
+		SimpleOOXmlFile *link = workbook->d_func()->externalLinks[i].data();
+        contentTypes->addExternalLinkName(QStringLiteral("externalLink%1").arg(i+1));
+
+        zipWriter.addFile(QStringLiteral("xl/externalLinks/externalLink%1.xml").arg(i+1), link->saveToXmlData());
+		Relationships *rel = link->relationships();
+		if (!rel->isEmpty())
+            zipWriter.addFile(QStringLiteral("xl/externalLinks/_rels/externalLink%1.xml.rels").arg(i+1), rel->saveToXmlData());
+	}
+
+	// save workbook xml file
+	contentTypes->addWorkbook();
+	zipWriter.addFile(QStringLiteral("xl/workbook.xml"), workbook->saveToXmlData());
+	zipWriter.addFile(QStringLiteral("xl/_rels/workbook.xml.rels"), workbook->relationships()->saveToXmlData());
+
+	// save drawing xml files
+    for (int i=0; i<workbook->drawings().size(); ++i)
+    {
+        contentTypes->addDrawingName(QStringLiteral("drawing%1").arg(i+1));
+
+		Drawing *drawing = workbook->drawings()[i];
+        zipWriter.addFile(QStringLiteral("xl/drawings/drawing%1.xml").arg(i+1), drawing->saveToXmlData());
+		if (!drawing->relationships()->isEmpty())
+            zipWriter.addFile(QStringLiteral("xl/drawings/_rels/drawing%1.xml.rels").arg(i+1), drawing->relationships()->saveToXmlData());
+	}
+
+	// save docProps app/core xml file
+    const auto docPropNames = q->documentPropertyNames();
+    for (const QString &name : docPropNames) {
+		docPropsApp.setProperty(name, q->documentProperty(name));
+		docPropsCore.setProperty(name, q->documentProperty(name));
+	}
+	contentTypes->addDocPropApp();
+	contentTypes->addDocPropCore();
+	zipWriter.addFile(QStringLiteral("docProps/app.xml"), docPropsApp.saveToXmlData());
+	zipWriter.addFile(QStringLiteral("docProps/core.xml"), docPropsCore.saveToXmlData());
+
+	// save sharedStrings xml file
+	if (!workbook->sharedStrings()->isEmpty()) {
+		contentTypes->addSharedString();
+		zipWriter.addFile(QStringLiteral("xl/sharedStrings.xml"), workbook->sharedStrings()->saveToXmlData());
+	}
+
+    // save calc chain [dev16]
+    contentTypes->addCalcChain();
+    zipWriter.addFile(QStringLiteral("xl/calcChain.xml"), workbook->styles()->saveToXmlData());
+
+	// save styles xml file
+	contentTypes->addStyles();
+	zipWriter.addFile(QStringLiteral("xl/styles.xml"), workbook->styles()->saveToXmlData());
+
+	// save theme xml file
+	contentTypes->addTheme();
+	zipWriter.addFile(QStringLiteral("xl/theme/theme1.xml"), workbook->theme()->saveToXmlData());
+
+	// save chart xml files
+    for (int i=0; i<workbook->chartFiles().size(); ++i)
+    {
+        contentTypes->addChartName(QStringLiteral("chart%1").arg(i+1));
+		QSharedPointer<Chart> cf = workbook->chartFiles()[i];
+        zipWriter.addFile(QStringLiteral("xl/charts/chart%1.xml").arg(i+1), cf->saveToXmlData());
+	}
+
+	// save image files
+    const auto mfs = workbook->mediaFiles();
+    for (int i=0; i < mfs.size(); ++i)
+    {
+        auto mf = mfs[i];
+		if (!mf->mimeType().isEmpty())
+			contentTypes->addDefault(mf->suffix(), mf->mimeType());
+
+        zipWriter.addFile(QStringLiteral("xl/media/image%1.%2").arg(i+1).arg(mf->suffix()), mf->contents());
+	}
+
+	// save root .rels xml file
+	Relationships rootrels;
+	rootrels.addDocumentRelationship(QStringLiteral("/officeDocument"), QStringLiteral("xl/workbook.xml"));
+	rootrels.addPackageRelationship(QStringLiteral("/metadata/core-properties"), QStringLiteral("docProps/core.xml"));
+	rootrels.addDocumentRelationship(QStringLiteral("/extended-properties"), QStringLiteral("docProps/app.xml"));
+	zipWriter.addFile(QStringLiteral("_rels/.rels"), rootrels.saveToXmlData());
+
+	// save content types xml file
+	zipWriter.addFile(QStringLiteral("[Content_Types].xml"), contentTypes->saveToXmlData());
+
+	zipWriter.close();
+	return true;
+}
+
+bool DocumentPrivate::copyStyle(const QString &from, const QString &to)
+{
+	// create a temp file because the zip writer cannot modify already existing zips
+	QTemporaryFile tempFile;
+	tempFile.open();
+	tempFile.close();
+	QString temFilePath = QFileInfo(tempFile).absoluteFilePath();
+
+	ZipWriter temporalZip(temFilePath);
+
+	ZipReader zipReader(from);
+	QStringList filePaths = zipReader.filePaths();
+
+    QSharedPointer<ZipReader> toReader = QSharedPointer<ZipReader>(new ZipReader(to));
+
+	QStringList toFilePaths = toReader->filePaths();
+
+	// copy all files from "to" zip except those related to style
+	for (int i = 0; i < toFilePaths.size(); i++) {
+        if (toFilePaths[i].contains(QLatin1String("xl/styles"))) {
+			if (filePaths.contains(toFilePaths[i])) {	// style file exist in 'from' as well
+				// modify style file
+                std::string fromData = QString::fromUtf8(zipReader.fileData(toFilePaths[i])).toStdString();
+                std::string toData = QString::fromUtf8(toReader->fileData(toFilePaths[i])).toStdString();
+				// copy default theme style from 'from' to 'to'
+				toData = xlsxDocumentCpp::copyTag(fromData, toData, "dxfs");
+				temporalZip.addFile(toFilePaths.at(i), QString::fromUtf8(toData.c_str()).toUtf8());
+
+				continue;
+			}
+		}
+
+        if (toFilePaths[i].contains(QLatin1String("xl/workbook"))) {
+			if (filePaths.contains(toFilePaths[i])) {	// workbook file exist in 'from' as well
+				// modify workbook file
+                std::string fromData = QString::fromUtf8(zipReader.fileData(toFilePaths[i])).toStdString();
+                std::string toData = QString::fromUtf8(toReader->fileData(toFilePaths[i])).toStdString();
+				// copy default theme style from 'from' to 'to'
+				toData = xlsxDocumentCpp::copyTag(fromData, toData, "workbookPr");
+				temporalZip.addFile(toFilePaths.at(i), QString::fromUtf8(toData.c_str()).toUtf8());
+				continue;
+			}
+		}
+
+        if (toFilePaths[i].contains(QLatin1String("xl/worksheets/sheet"))) {
+			if (filePaths.contains(toFilePaths[i])) {	// sheet file exist in 'from' as well
+				// modify sheet file
+                std::string fromData = QString::fromUtf8(zipReader.fileData(toFilePaths[i])).toStdString();
+                std::string toData = QString::fromUtf8(toReader->fileData(toFilePaths[i])).toStdString();
+				// copy "conditionalFormatting" from 'from' to 'to'
+				toData = xlsxDocumentCpp::copyTag(fromData, toData, "conditionalFormatting");
+				temporalZip.addFile(toFilePaths.at(i), QString::fromUtf8(toData.c_str()).toUtf8());
+				continue;
+			}
+		}
+
+		QByteArray data = toReader->fileData(toFilePaths.at(i));
+		temporalZip.addFile(toFilePaths.at(i), data);
+	}
+
+	temporalZip.close();
+
+    toReader.clear();
+
+	tempFile.close();
+
+	QFile::remove(to);
+	tempFile.copy(to);
+
+	return true;
+}
+
+/*!
+  \class Document
+  \inmodule QtXlsx
+  \brief The Document class provides a API that is used to handle the contents of .xlsx files.
+
+*/
+
+/*!
+ * Creates a new empty xlsx document.
+ * The \a parent argument is passed to QObject's constructor.
+ */
+Document::Document(QObject *parent) :
+	QObject(parent), d_ptr(new DocumentPrivate(this))
+{
+	d_ptr->init();
+}
+
+/*!
+ * \overload
+ * Try to open an existing xlsx document named \a name.
+ * The \a parent argument is passed to QObject's constructor.
+ */
+Document::Document(const QString &name, 
+					QObject *parent) :
+	QObject(parent), 
+	d_ptr(new DocumentPrivate(this))
+{
+	d_ptr->packageName = name; 
+
+	if (QFile::exists(name)) 
+	{
+		QFile xlsx(name);
+		if (xlsx.open(QFile::ReadOnly))
+		{
+			if (! d_ptr->loadPackage(&xlsx))
+			{
+				// NOTICE: failed to load package 
+			}
+		}
+	}
+
+	d_ptr->init();
+}
+
+/*!
+ * \overload
+ * Try to open an existing xlsx document from \a device.
+ * The \a parent argument is passed to QObject's constructor.
+ */
+Document::Document(QIODevice *device, QObject *parent) :
+	QObject(parent), d_ptr(new DocumentPrivate(this))
+{
+	if (device && device->isReadable())
+	{
+		if (!d_ptr->loadPackage(device))
+		{
+			// NOTICE: failed to load package 
+		}
+	}
+	d_ptr->init();
+}
+
+/*!
+	\overload
+
+	Write \a value to cell \a row_column with the given \a format.
+ */
+bool Document::write(const CellReference &row_column, const QVariant &value, const Format &format)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->write(row_column, value, format);
+	return false;
+}
+
+/*!
+ * Write \a value to cell (\a row, \a col) with the \a format.
+ * Returns true on success.
+ */
+bool Document::write(int row, int col, const QVariant &value, const Format &format)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->write(row, col, value, format);
+	return false;
+}
+
+/*!
+	\overload
+	Returns the contents of the cell \a cell.
+
+	\sa cellAt()
+*/
+QVariant Document::read(const CellReference &cell) const
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->read(cell);
+	return QVariant();
+}
+
+/*!
+	Returns the contents of the cell (\a row, \a col).
+
+	\sa cellAt()
+ */
+QVariant Document::read(int row, int col) const
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->read(row, col);
+	return QVariant();
+}
+
+/*!
+ * Insert an \a image to current active worksheet at the position \a row, \a column
+ * Returns ture if success.
+ */
+int Document::insertImage(int row, int column, const QImage &image)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->insertImage(row, column, image);
+
+    return 0;
+}
+
+bool Document::getImage(int imageIndex, QImage& img)
+{
+    if (Worksheet *sheet = currentWorksheet())
+        return sheet->getImage(imageIndex, img);
+
+    return  false;
+}
+
+bool Document::getImage(int row, int col, QImage &img)
+{
+    if (Worksheet *sheet = currentWorksheet())
+        return sheet->getImage(row, col, img);
+
+    return  false;
+}
+
+uint Document::getImageCount()
+{
+    if (Worksheet *sheet = currentWorksheet())
+        return sheet->getImageCount();
+
+    return 0;
+}
+
+
+/*!
+ * Creates an chart with the given \a size and insert it to the current
+ * active worksheet at the position \a row, \a col.
+ * The chart will be returned.
+ */
+Chart *Document::insertChart(int row, int col, const QSize &size)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->insertChart(row, col, size);
+	return 0;
+}
+
+/*!
+  Merge a \a range of cells. The first cell should contain the data and the others should
+  be blank. All cells will be applied the same style if a valid \a format is given.
+  Returns true on success.
+
+  \note All cells except the top-left one will be cleared.
+ */
+bool Document::mergeCells(const CellRange &range, const Format &format)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->mergeCells(range, format);
+	return false;
+}
+
+/*!
+  Unmerge the cells in the \a range.
+  Returns true on success.
+*/
+bool Document::unmergeCells(const CellRange &range)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->unmergeCells(range);
+	return false;
+}
+
+/*!
+  Sets width in characters of columns with the given \a range and \a width.
+  Returns true on success.
+ */
+bool Document::setColumnWidth(const CellRange &range, double width)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->setColumnWidth(range, width);
+	return false;
+}
+
+/*!
+  Sets format property of columns with the gien \a range and \a format.
+  Returns true on success.
+ */
+bool Document::setColumnFormat(const CellRange &range, const Format &format)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->setColumnFormat(range, format);
+	return false;
+}
+
+/*!
+  Sets hidden property of columns \a range to \a hidden. Columns are 1-indexed.
+  Hidden columns are not visible.
+  Returns true on success.
+ */
+bool Document::setColumnHidden(const CellRange &range, bool hidden)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->setColumnWidth(range, hidden);
+	return false;
+}
+
+/*!
+  Sets width in characters \a column to \a width. Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Document::setColumnWidth(int column, double width)
+{
+	return setColumnWidth(column,column,width);
+}
+
+/*!
+  Sets format property \a column to \a format. Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Document::setColumnFormat(int column, const Format &format)
+{
+	return setColumnFormat(column,column,format);
+}
+
+/*!
+  Sets hidden property of a \a column. Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Document::setColumnHidden(int column, bool hidden)
+{
+	return setColumnHidden(column,column,hidden);
+}
+
+/*!
+  Sets width in characters for columns [\a colFirst, \a colLast]. Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Document::setColumnWidth(int colFirst, int colLast, double width)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->setColumnWidth(colFirst, colLast, width);
+	return false;
+}
+
+/*!
+  Sets format property of columns [\a colFirst, \a colLast] to \a format.
+  Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Document::setColumnFormat(int colFirst, int colLast, const Format &format)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->setColumnFormat(colFirst, colLast, format);
+	return false;
+}
+
+
+/*!
+  Sets hidden property of columns [\a colFirst, \a colLast] to \a hidden.
+  Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Document::setColumnHidden(int colFirst, int colLast, bool hidden)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->setColumnHidden(colFirst, colLast, hidden);
+	return false;
+}
+
+/*!
+  Returns width of the \a column in characters of the normal font.
+  Columns are 1-indexed.
+  Returns true on success.
+ */
+double Document::columnWidth(int column)
+{
+	if (Worksheet *sheet = currentWorksheet())
+	  return sheet->columnWidth(column);
+	return 0.0;
+}
+
+/*!
+  Returns formatting of the \a column. Columns are 1-indexed.
+ */
+Format Document::columnFormat(int column)
+{
+	if (Worksheet *sheet = currentWorksheet())
+	   return sheet->columnFormat(column);
+	return Format();
+}
+
+/*!
+  Returns true if \a column is hidden. Columns are 1-indexed.
+ */
+bool Document::isColumnHidden(int column)
+{
+	if (Worksheet *sheet = currentWorksheet())
+	   return sheet->isColumnHidden(column);
+	return false;
+}
+
+/*!
+  Sets the \a format of the \a row.
+  Rows are 1-indexed.
+
+  Returns true if success.
+*/
+bool Document::setRowFormat(int row, const Format &format)
+{
+	return setRowFormat(row,row, format);
+}
+
+/*!
+  Sets the \a format of the rows including and between \a rowFirst and \a rowLast.
+  Rows are 1-indexed.
+
+  Returns true if success.
+*/
+bool Document::setRowFormat(int rowFirst, int rowLast, const Format &format)
+{
+	if (Worksheet *sheet = currentWorksheet())
+	   return sheet->setRowFormat(rowFirst, rowLast, format);
+	return false;
+}
+
+/*!
+  Sets the \a hidden property of the row \a row.
+  Rows are 1-indexed. If hidden is true rows will not be visible.
+
+  Returns true if success.
+*/
+bool Document::setRowHidden(int row, bool hidden)
+{
+	return setRowHidden(row,row,hidden);
+}
+
+/*!
+  Sets the \a hidden property of the rows including and between \a rowFirst and \a rowLast.
+  Rows are 1-indexed. If hidden is true rows will not be visible.
+
+  Returns true if success.
+*/
+bool Document::setRowHidden(int rowFirst, int rowLast, bool hidden)
+{
+	if (Worksheet *sheet = currentWorksheet())
+	   return sheet->setRowHidden(rowFirst, rowLast, hidden);
+	return false;
+}
+
+/*!
+  Sets the \a height of the row \a row.
+  Row height measured in point size.
+  Rows are 1-indexed.
+
+  Returns true if success.
+*/
+bool Document::setRowHeight(int row, double height)
+{
+	return setRowHeight(row,row,height);
+}
+
+/*!
+  Sets the \a height of the rows including and between \a rowFirst and \a rowLast.
+  Row height measured in point size.
+  Rows are 1-indexed.
+
+  Returns true if success.
+*/
+bool Document::setRowHeight(int rowFirst, int rowLast, double height)
+{
+	if (Worksheet *sheet = currentWorksheet())
+	   return sheet->setRowHeight(rowFirst, rowLast, height);
+	return false;
+}
+
+/*!
+ Returns height of \a row in points.
+*/
+double Document::rowHeight(int row)
+{
+   if (Worksheet *sheet = currentWorksheet())
+	  return sheet->rowHeight(row);
+	return 0.0;
+}
+
+/*!
+ Returns format of \a row.
+*/
+Format Document::rowFormat(int row)
+{
+	if (Worksheet *sheet = currentWorksheet())
+	   return sheet->rowFormat(row);
+	 return Format();
+}
+
+/*!
+ Returns true if \a row is hidden.
+*/
+bool Document::isRowHidden(int row)
+{
+	if (Worksheet *sheet = currentWorksheet())
+	   return sheet->isRowHidden(row);
+	 return false;
+}
+
+/*!
+   Groups rows from \a rowFirst to \a rowLast with the given \a collapsed.
+   Returns false if error occurs.
+ */
+bool Document::groupRows(int rowFirst, int rowLast, bool collapsed)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->groupRows(rowFirst, rowLast, collapsed);
+	return false;
+}
+
+/*!
+   Groups columns from \a colFirst to \a colLast with the given \a collapsed.
+   Returns false if error occurs.
+ */
+bool Document::groupColumns(int colFirst, int colLast, bool collapsed)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->groupColumns(colFirst, colLast, collapsed);
+	return false;
+}
+
+/*!
+ *  Add a data \a validation rule for current worksheet. Returns true if successful.
+ */
+bool Document::addDataValidation(const DataValidation &validation)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->addDataValidation(validation);
+	return false;
+}
+
+/*!
+ *  Add a  conditional formatting \a cf for current worksheet. Returns true if successful.
+ */
+bool Document::addConditionalFormatting(const ConditionalFormatting &cf)
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->addConditionalFormatting(cf);
+	return false;
+}
+
+/*!
+ * \overload
+ * Returns the cell at the position \a pos. If there is no cell at
+ * the specified position, the function returns 0.
+ *
+ * \sa read()
+ */
+Cell *Document::cellAt(const CellReference &pos) const
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->cellAt(pos);
+	return 0;
+}
+
+/*!
+ * Returns the cell at the given \a row and \a col. If there
+ * is no cell at the specified position, the function returns 0.
+ *
+ * \sa read()
+ */
+Cell *Document::cellAt(int row, int col) const
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->cellAt(row, col);
+	return 0;
+}
+
+/*!
+ * \brief Create a defined name in the workbook with the given \a name, \a formula, \a comment
+ *  and \a scope.
+ *
+ * \param name The defined name.
+ * \param formula The cell or range that the defined name refers to.
+ * \param scope The name of one worksheet, or empty which means golbal scope.
+ * \return Return false if the name invalid.
+ */
+bool Document::defineName(const QString &name, const QString &formula, const QString &comment, const QString &scope)
+{
+	Q_D(Document);
+
+	return d->workbook->defineName(name, formula, comment, scope);
+}
+
+/*!
+	Return the range that contains cell data.
+ */
+CellRange Document::dimension() const
+{
+	if (Worksheet *sheet = currentWorksheet())
+		return sheet->dimension();
+	return CellRange();
+}
+
+/*!
+ * Returns the value of the document's \a key property.
+ */
+QString Document::documentProperty(const QString &key) const
+{
+	Q_D(const Document);
+    auto it = d->documentProperties.constFind(key);
+    if (it != d->documentProperties.constEnd())
+        return it.value();
+	else
+		return QString();
+}
+
+/*!
+	Set the document properties such as Title, Author etc.
+
+	The method can be used to set the document properties of the Excel
+	file created by Qt Xlsx. These properties are visible when you use the
+	Office Button -> Prepare -> Properties option in Excel and are also
+	available to external applications that read or index windows files.
+
+	The \a property \a key that can be set are:
+
+	\list
+	\li title
+	\li subject
+	\li creator
+	\li manager
+	\li company
+	\li category
+	\li keywords
+	\li description
+	\li status
+	\endlist
+*/
+void Document::setDocumentProperty(const QString &key, const QString &property)
+{
+	Q_D(Document);
+	d->documentProperties[key] = property;
+}
+
+/*!
+ * Returns the names of all properties that were addedusing setDocumentProperty().
+ */
+QStringList Document::documentPropertyNames() const
+{
+	Q_D(const Document);
+	return d->documentProperties.keys();
+}
+
+/*!
+ * Return the internal Workbook object.
+ */
+Workbook *Document::workbook() const
+{
+	Q_D(const Document);
+    return d->workbook.data();
+}
+
+/*!
+ * Returns the sheet object named \a sheetName.
+ */
+AbstractSheet *Document::sheet(const QString &sheetName) const
+{
+	Q_D(const Document);
+	return d->workbook->sheet(sheetNames().indexOf(sheetName));
+}
+
+/*!
+ * Creates and append an sheet with the given \a name and \a type.
+ * Return true if success.
+ */
+bool Document::addSheet(const QString &name, AbstractSheet::SheetType type)
+{
+	Q_D(Document);
+	return d->workbook->addSheet(name, type);
+}
+
+/*!
+ * Creates and inserts an document with the given \a name and \a type at the \a index.
+ * Returns false if the \a name already used.
+ */
+bool Document::insertSheet(int index, const QString &name, AbstractSheet::SheetType type)
+{
+	Q_D(Document);
+	return d->workbook->insertSheet(index, name, type);
+}
+
+/*!
+   Rename the worksheet from \a oldName to \a newName.
+   Returns true if the success.
+ */
+bool Document::renameSheet(const QString &oldName, const QString &newName)
+{
+	Q_D(Document);
+	if (oldName == newName)
+		return false;
+	return d->workbook->renameSheet(sheetNames().indexOf(oldName), newName);
+}
+
+/*!
+   Make a copy of the worksheet \a srcName with the new name \a distName.
+   Returns true if the success.
+ */
+bool Document::copySheet(const QString &srcName, const QString &distName)
+{
+	Q_D(Document);
+	if (srcName == distName)
+		return false;
+	return d->workbook->copySheet(sheetNames().indexOf(srcName), distName);
+}
+
+/*!
+   Move the worksheet \a srcName to the new pos \a distIndex.
+   Returns true if the success.
+ */
+bool Document::moveSheet(const QString &srcName, int distIndex)
+{
+	Q_D(Document);
+	return d->workbook->moveSheet(sheetNames().indexOf(srcName), distIndex);
+}
+
+/*!
+   Delete the worksheet \a name.
+   Returns true if current sheet was deleted successfully.
+ */
+bool Document::deleteSheet(const QString &name)
+{
+	Q_D(Document);
+	return d->workbook->deleteSheet(sheetNames().indexOf(name));
+}
+
+/*!
+ * \brief Return pointer of current sheet.
+ */
+AbstractSheet *Document::currentSheet() const
+{
+	Q_D(const Document);
+
+	return d->workbook->activeSheet();
+}
+
+/*!
+ * \brief Return pointer of current worksheet.
+ * If the type of sheet is not AbstractSheet::ST_WorkSheet, then 0 will be returned.
+ */
+Worksheet *Document::currentWorksheet() const
+{
+	AbstractSheet *st = currentSheet();
+	if (st && st->sheetType() == AbstractSheet::ST_WorkSheet)
+		return static_cast<Worksheet *>(st);
+	else
+		return 0;
+}
+
+/*!
+ * \brief Set worksheet named \a name to be active sheet.
+ * Returns true if success.
+ */
+bool Document::selectSheet(const QString &name)
+{
+	Q_D(Document);
+	return d->workbook->setActiveSheet(sheetNames().indexOf(name));
+}
+
+/*!
+ * \brief Set worksheet whose index is \a index to be active sheet.
+ * Returns true if success.
+ */
+bool Document::selectSheet(int index)
+{
+	Q_D(Document);
+	return d->workbook->setActiveSheet(index);
+}
+
+/*!
+ * Returns the names of worksheets contained in current document.
+ */
+QStringList Document::sheetNames() const
+{
+	Q_D(const Document);
+	return d->workbook->worksheetNames();
+}
+
+/*!
+ * Save current document to the filesystem. If no name specified when
+ * the document constructed, a default name "book1.xlsx" will be used.
+ * Returns true if saved successfully.
+ */
+bool Document::save() const
+{
+	Q_D(const Document);
+	QString name = d->packageName.isEmpty() ? d->defaultPackageName : d->packageName;
+
+	return saveAs(name);
+}
+
+/*!
+ * Saves the document to the file with the given \a name.
+ * Returns true if saved successfully.
+ */
+bool Document::saveAs(const QString &name) const
+{
+	QFile file(name);
+	if (file.open(QIODevice::WriteOnly))
+		return saveAs(&file);
+	return false;
+}
+
+/*!
+ * \overload
+ * This function writes a document to the given \a device.
+ *
+ * \warning The \a device will be closed when this function returned.
+ */
+bool Document::saveAs(QIODevice *device) const
+{
+	Q_D(const Document);
+	return d->savePackage(device);
+}
+
+bool Document::isLoadPackage() const
+{
+	Q_D(const Document);
+	return d->isLoad; 
+}
+
+bool Document::load() const
+{
+	return isLoadPackage();
+}
+
+bool Document::copyStyle(const QString &from, const QString &to) {
+	return DocumentPrivate::copyStyle(from, to);
+}
+
+/*!
+ * Destroys the document and cleans up.
+ */
+Document::~Document()
+{
+	delete d_ptr;
+}
+
+//  add by liufeijin 20181025 {{
+bool Document::changeimage(int filenoinmidea, QString newfile)
+{
+	Q_D(const Document);
+
+    QImage newpic(newfile);
+	
+    auto mediaFileToLoad = d->workbook->mediaFiles();
+    const auto mf = mediaFileToLoad[filenoinmidea];
+	
+	const QString suffix = newfile.mid(newfile.lastIndexOf(QLatin1Char('.'))+1);
+	QString mimetypemy;
+    if(QString::compare(QLatin1String("jpg"), suffix, Qt::CaseInsensitive)==0)
+       mimetypemy=QStringLiteral("image/jpeg");
+    if(QString::compare(QLatin1String("bmp"), suffix, Qt::CaseInsensitive)==0)
+       mimetypemy=QStringLiteral("image/bmp");
+    if(QString::compare(QLatin1String("gif"), suffix, Qt::CaseInsensitive)==0)
+       mimetypemy=QStringLiteral("image/gif");
+    if(QString::compare(QLatin1String("png"), suffix, Qt::CaseInsensitive)==0)
+       mimetypemy=QStringLiteral("image/png");
+	
+	QByteArray ba;
+	QBuffer buffer(&ba);
+	buffer.setBuffer(&ba);
+	buffer.open(QIODevice::WriteOnly);
+	newpic.save(&buffer,suffix.toLocal8Bit().data());
+	
+	mf->set(ba,suffix,mimetypemy);
+	mediaFileToLoad[filenoinmidea]=mf;
+	
+	return true;
+}
+// liufeijin }}
+
+
+/*!
+  Returns map of columns with there maximal width
+ */
+QMap<int, int> Document::getMaximalColumnWidth(int firstRow, int lastRow)
+{
+    const int defaultPixelSize = 11;    //Default font pixel size of excel?
+    int maxRows = -1;
+    int maxCols = -1;
+    QMap<int, int> colWidth;
+    if (!currentWorksheet()) return colWidth;
+    QVector<CellLocation> cellLocation = currentWorksheet()->getFullCells(&maxRows, &maxCols);
+    
+    for(int i=0; i < cellLocation.size(); i++)
+    {
+        int col = cellLocation.at(i).col;
+        int row = cellLocation.at(i).row;
+        int fs = cellLocation.at(i).cell->format().fontSize();
+        if( fs <= 0)
+        {
+            fs = defaultPixelSize;
+        }
+
+//        QString str = cellLocation.at(i).cell.data()->value().toString();
+        QString str = read(row, col).toString();
+
+        double w = str.length() * double(fs) / defaultPixelSize + 1; // width not perfect, but works reasonably well
+
+        if( (row >= firstRow) && (row <= lastRow))
+        {
+            if( w > colWidth.value(col))
+            {
+                colWidth.insert(col, int(w));
+            }
+        }
+    }
+
+    return colWidth;
+}
+
+
+/*!
+  Auto ets width in characters of columns with the given \a range.
+  Returns true on success.
+ */
+bool Document::autosizeColumnWidth(const CellRange &range)
+{
+    bool erg = false;
+
+    if( !range.isValid())
+    {
+        return false;
+    }
+
+    const QMap<int, int> colWidth = getMaximalColumnWidth(range.firstRow(), range.lastRow());
+    auto it = colWidth.constBegin();
+    while (it != colWidth.constEnd()) {
+        if( (it.key() >= range.firstColumn()) && (it.key() <= range.lastColumn()) )
+        {
+            erg |= setColumnWidth(it.key(), it.value());
+        }
+        ++it;
+    }
+
+    return erg;
+}
+
+
+/*!
+  Auto sets width in characters \a column . Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Document::autosizeColumnWidth(int column)
+{
+    bool erg = false;
+
+    const QMap<int, int> colWidth = getMaximalColumnWidth();
+    auto it = colWidth.constBegin();
+    while (it != colWidth.constEnd()) {
+        if( it.key() == column)
+        {
+            erg |= setColumnWidth(it.key(), it.value());
+        }
+        ++it;
+    }
+
+    return erg;
+}
+
+
+/*!
+  Auto sets width in characters for columns [\a colFirst, \a colLast]. Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Document::autosizeColumnWidth(int colFirst, int colLast)
+{
+    Q_UNUSED(colFirst)
+    Q_UNUSED(colLast)
+    bool erg = false;
+
+    const QMap<int, int> colWidth = getMaximalColumnWidth();
+    auto it = colWidth.constBegin();
+    while (it != colWidth.constEnd()) {
+        if( (it.key() >= colFirst) && (it.key() <= colLast) )
+        {
+            erg |= setColumnWidth(it.key(), it.value());
+        }
+        ++it;
+    }
+
+    return erg;
+}
+
+
+/*!
+  Auto sets width in characters for all columns.
+  Returns true on success.
+ */
+bool Document::autosizeColumnWidth(void)
+{
+    bool erg = false;
+
+    const QMap<int, int> colWidth = getMaximalColumnWidth();
+    auto it = colWidth.constBegin();
+    while (it != colWidth.constEnd()) {
+        erg |= setColumnWidth(it.key(), it.value());
+        ++it;
+    }
+
+    return erg;
+}
+
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxdrawing.cpp b/internal_system_v1/QXlsx/source/xlsxdrawing.cpp
new file mode 100644
index 0000000..2675310
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxdrawing.cpp
@@ -0,0 +1,84 @@
+// xlsxdrawing.cpp
+
+#include <QtGlobal>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QBuffer>
+
+#include "xlsxdrawing_p.h"
+#include "xlsxdrawinganchor_p.h"
+#include "xlsxabstractsheet.h"
+
+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
+            {
+                DrawingAbsoluteAnchor * anchor = new DrawingAbsoluteAnchor(this);
+                anchor->loadFromXml(reader);
+            }
+            else if (reader.name() == QLatin1String("oneCellAnchor")) // CT_OneCellAnchor
+            {
+                DrawingOneCellAnchor * anchor = new DrawingOneCellAnchor(this);
+                anchor->loadFromXml(reader);
+            }
+            else if (reader.name() == QLatin1String("twoCellAnchor")) // CT_TwoCellAnchor
+            {
+                DrawingTwoCellAnchor * anchor = new DrawingTwoCellAnchor(this);
+                anchor->loadFromXml(reader);
+            }
+        }
+    }
+
+    return true;
+}
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxdrawinganchor.cpp b/internal_system_v1/QXlsx/source/xlsxdrawinganchor.cpp
new file mode 100644
index 0000000..89d27eb
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxdrawinganchor.cpp
@@ -0,0 +1,1203 @@
+// xlsxdrawinganchor.cpp
+
+#include <QtGlobal>
+#include <QDebug>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+#include <QBuffer>
+#include <QDir>
+
+#include "xlsxdrawinganchor_p.h"
+#include "xlsxdrawing_p.h"
+#include "xlsxmediafile_p.h"
+#include "xlsxchart.h"
+#include "xlsxworkbook.h"
+#include "xlsxutility_p.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+/*
+     The vertices that define the position of a graphical object
+     within the worksheet in pixels.
+
+             +------------+------------+
+             |     A      |      B     |
+       +-----+------------+------------+
+       |     |(x1,y1)     |            |
+       |  1  |(A1)._______|______      |
+       |     |    |              |     |
+       |     |    |              |     |
+       +-----+----|    OBJECT    |-----+
+       |     |    |              |     |
+       |  2  |    |______________.     |
+       |     |            |        (B2)|
+       |     |            |     (x2,y2)|
+       +---- +------------+------------+
+
+     Example of an object that covers some of the area from cell A1 to  B2.
+
+     Based on the width and height of the object we need to calculate 8 vars:
+
+         col_start, row_start, col_end, row_end, x1, y1, x2, y2.
+
+     We also calculate the absolute x and y position of the top left vertex of
+     the object. This is required for images.
+
+     The width and height of the cells that the object occupies can be
+     variable and have to be taken into account.
+*/
+
+//anchor
+
+DrawingAnchor::DrawingAnchor(Drawing *drawing, ObjectType objectType)
+    :m_drawing(drawing), m_objectType(objectType)
+{
+    m_drawing->anchors.append(this);
+    m_id = m_drawing->anchors.size();//must be unique in one drawing{x}.xml file.
+}
+
+DrawingAnchor::~DrawingAnchor()
+{
+
+}
+
+void DrawingAnchor::setObjectPicture(const QImage &img)
+{
+    QByteArray ba;
+    QBuffer buffer(&ba);
+    buffer.open(QIODevice::WriteOnly);
+    img.save(&buffer, "PNG");
+
+    m_pictureFile = std::make_shared<MediaFile>(ba, QStringLiteral("png"), QStringLiteral("image/png"));
+    m_drawing->workbook->addMediaFile(m_pictureFile);
+
+    m_objectType = Picture;
+}
+
+bool DrawingAnchor::getObjectPicture(QImage &img)
+{
+    if ( m_pictureFile == nullptr )
+        return false;
+
+    bool ret = img.loadFromData( m_pictureFile->contents() );
+    return ret;
+}
+
+//{{ liufeijin
+void DrawingAnchor::setObjectShape(const QImage &img)
+{
+    QByteArray ba;
+    QBuffer buffer(&ba);
+    buffer.open(QIODevice::WriteOnly);
+    img.save(&buffer, "PNG");
+
+    m_pictureFile = std::make_shared<MediaFile>(ba, QStringLiteral("png"), QStringLiteral("image/png"));
+    m_drawing->workbook->addMediaFile(m_pictureFile);
+
+    m_objectType = Shape;
+}
+//}}
+
+void DrawingAnchor::setObjectGraphicFrame(QSharedPointer<Chart> chart)
+{
+    m_chartFile = chart;
+    m_drawing->workbook->addChartFile(chart);
+
+    m_objectType = GraphicFrame;
+}
+
+int DrawingAnchor::row() const
+{
+    return -1;
+}
+
+int DrawingAnchor::col() const
+{
+    return -1;
+}
+
+QPoint DrawingAnchor::loadXmlPos(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("pos"));
+
+    QPoint pos;
+    QXmlStreamAttributes attrs = reader.attributes();
+    pos.setX(attrs.value(QLatin1String("x")).toInt());
+    pos.setY(attrs.value(QLatin1String("y")).toInt());
+    return pos;
+}
+
+QSize DrawingAnchor::loadXmlExt(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("ext"));
+
+    QSize size;
+    QXmlStreamAttributes attrs = reader.attributes();
+    size.setWidth(attrs.value(QLatin1String("cx")).toInt());
+    size.setHeight(attrs.value(QLatin1String("cy")).toInt());
+    return size;
+}
+
+XlsxMarker DrawingAnchor::loadXmlMarker(QXmlStreamReader &reader, const QString &node)
+{
+    Q_ASSERT(reader.name() == node);
+
+    int col = 0;
+    int colOffset = 0;
+    int row = 0;
+    int rowOffset = 0;
+    while (!reader.atEnd())
+    {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            if (reader.name() == QLatin1String("col"))
+            {
+                col = reader.readElementText().toInt();
+            }
+            else if (reader.name() == QLatin1String("colOff"))
+            {
+                colOffset = reader.readElementText().toInt();
+            }
+            else if (reader.name() == QLatin1String("row"))
+            {
+                row = reader.readElementText().toInt();
+            }
+            else if (reader.name() == QLatin1String("rowOff"))
+            {
+                rowOffset = reader.readElementText().toInt();
+            }
+        }
+        else if (reader.tokenType() == QXmlStreamReader::EndElement
+                   && reader.name() == node)
+        {
+            break;
+        }
+    }
+
+    return XlsxMarker(row, col, rowOffset, colOffset);
+}
+
+void DrawingAnchor::loadXmlObject(QXmlStreamReader &reader)
+{
+    /*
+    <xsd:group name="EG_ObjectChoices">
+        <xsd:sequence>
+            <xsd:choice minOccurs="1" maxOccurs="1">
+                <xsd:element name="sp" type="CT_Shape"/>
+                <xsd:element name="grpSp" type="CT_GroupShape"/>
+                <xsd:element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
+                <xsd:element name="cxnSp" type="CT_Connector"/>
+                <xsd:element name="pic" type="CT_Picture"/>
+                <xsd:element name="contentPart" type="CT_Rel"/>
+            </xsd:choice>
+        </xsd:sequence>
+    </xsd:group>
+    */
+
+    if (reader.name() == QLatin1String("sp")) // <xsd:element name="sp" type="CT_Shape"/>
+    {
+        // Shape
+        m_objectType = Shape;
+
+		//{{ liufeijin
+        sp_textlink = reader.attributes().value(QLatin1String("textlink")).toString();
+        sp_macro = reader.attributes().value(QLatin1String("macro")).toString();
+		//}} 
+
+        // <xsd:attribute name="macro" type="xsd:string" use="optional"/>
+        // <xsd:attribute name="textlink" type="xsd:string" use="optional"/>
+        // <xsd:attribute name="fLocksText" type="xsd:boolean" use="optional" default="true"/>
+        // <xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
+
+        loadXmlObjectShape(reader); // CT_Shape
+    }
+    else if (reader.name() == QLatin1String("grpSp")) // <xsd:element name="grpSp" type="CT_GroupShape"/>
+    {
+        //Group Shape
+        m_objectType = GroupShape;
+        loadXmlObjectGroupShape(reader);
+    }
+    else if (reader.name() == QLatin1String("graphicFrame")) // <xsd:element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
+    {
+        //Graphic Frame
+        m_objectType = GraphicFrame;
+        loadXmlObjectGraphicFrame(reader);
+    }
+    else if (reader.name() == QLatin1String("cxnSp")) // <xsd:element name="cxnSp" type="CT_Connector"/>
+    {
+        //Connection Shape
+        m_objectType = ConnectionShape;
+
+		// {{ liufeijin
+        cxnSp_macro = reader.attributes().value(QLatin1String("macro")).toString();
+		// }}
+
+        loadXmlObjectConnectionShape(reader);
+    }
+    else if (reader.name() == QLatin1String("pic")) // <xsd:element name="pic" type="CT_Picture"/>
+    {
+        // Picture
+        m_objectType = Picture;
+        loadXmlObjectPicture(reader);
+    }
+    else if (reader.name() == QLatin1String("contentPart")) // <xsd:element name="contentPart" type="CT_Rel"/>
+    {
+        // contentPart
+        /// TODO:
+    }
+}
+
+void DrawingAnchor::loadXmlObjectConnectionShape(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("cxnSp"));
+    bool hasoffext=false;
+    while (!reader.atEnd()) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("cNvPr")){
+                xsp_cNvPR_name= reader.attributes().value(QLatin1String("name")).toString();
+                xsp_cNvPR_id= reader.attributes().value(QLatin1String("id")).toString();
+             }else if(reader.name() == QLatin1String("spPr")){
+                 xbwMode= reader.attributes().value(QLatin1String("bwMode")).toString();
+            }else if(reader.name() == QLatin1String("xfrm")){
+                cxnSp_filpV= reader.attributes().value(QLatin1String("flipV")).toString();
+            }else if (reader.name() == QLatin1String("off")) {
+               posTA = loadXmlPos(reader);
+               hasoffext=true;
+            } else if (reader.name() == QLatin1String("ext")&&hasoffext) {
+               extTA = loadXmlExt(reader);
+               hasoffext=false;
+            }else if(reader.name() == QLatin1String("prstGeom")){
+                xprstGeom_prst= reader.attributes().value(QLatin1String("prst")).toString().trimmed();
+            }else if(reader.name() == QLatin1String("ln")){
+                xIn_algn= reader.attributes().value(QLatin1String("algn")).toString().trimmed();
+                xIn_cmpd= reader.attributes().value(QLatin1String("cmpd")).toString().trimmed();
+                xIn_cap= reader.attributes().value(QLatin1String("cap")).toString().trimmed();
+                xIn_w= reader.attributes().value(QLatin1String("w")).toString().trimmed();
+            }else if(reader.name() == QLatin1String("headEnd")){
+                x_headEnd_w= reader.attributes().value(QLatin1String("w")).toString().trimmed();
+                x_headEnd_len= reader.attributes().value(QLatin1String("len")).toString().trimmed();
+                x_headEnd_tyep= reader.attributes().value(QLatin1String("type")).toString().trimmed();
+            }else if(reader.name() == QLatin1String("tailEnd")){
+                x_tailEnd_w= reader.attributes().value(QLatin1String("w")).toString().trimmed();
+                x_tailEnd_len= reader.attributes().value(QLatin1String("len")).toString().trimmed();
+                x_tailEnd_tyep= reader.attributes().value(QLatin1String("type")).toString().trimmed();
+            }else if(reader.name() == QLatin1String("lnRef")){
+                Style_inref_idx= reader.attributes().value(QLatin1String("idx")).toString().trimmed();
+                reader.readNextStartElement();
+                if (reader.tokenType() == QXmlStreamReader::StartElement) {
+                    if(reader.name() == QLatin1String("schemeClr")){
+                        Style_inref_val=reader.attributes().value(QLatin1String("val")).toString().trimmed();
+                    }
+                }
+            }else if(reader.name() == QLatin1String("fillRef")){
+                style_fillref_idx= reader.attributes().value(QLatin1String("idx")).toString().trimmed();
+                reader.readNextStartElement();
+                if (reader.tokenType() == QXmlStreamReader::StartElement) {
+                    if(reader.name() == QLatin1String("schemeClr")){
+                       style_fillref_val=reader.attributes().value(QLatin1String("val")).toString().trimmed();
+                    }
+                }
+            }else if(reader.name() == QLatin1String("effectRef")){
+                style_effectref_idx= reader.attributes().value(QLatin1String("idx")).toString().trimmed();
+                reader.readNextStartElement();
+                if (reader.tokenType() == QXmlStreamReader::StartElement) {
+                    if(reader.name() == QLatin1String("schemeClr")){
+                      style_effectref_val=reader.attributes().value(QLatin1String("val")).toString().trimmed();
+                    }
+                }
+            }else if(reader.name() == QLatin1String("fontRef")){
+                style_forntref_idx= reader.attributes().value(QLatin1String("idx")).toString().trimmed();
+                reader.readNextStartElement();
+                if (reader.tokenType() == QXmlStreamReader::StartElement) {
+                    if(reader.name() == QLatin1String("schemeClr")){
+                        style_forntref_val=reader.attributes().value(QLatin1String("val")).toString().trimmed();
+                    }
+                }
+            }
+
+        } else if (reader.tokenType() == QXmlStreamReader::EndElement
+                   && reader.name() == QLatin1String("cxnSp")) {
+            break;
+        }
+    }
+
+    return;
+
+}
+
+void DrawingAnchor::loadXmlObjectGraphicFrame(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("graphicFrame"));
+
+    while (!reader.atEnd()) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("chart")) {
+                QString rId = reader.attributes().value(QLatin1String("r:id")).toString();
+                QString name = m_drawing->relationships()->getRelationshipById(rId).target;
+
+                const auto parts = splitPath(m_drawing->filePath());
+                QString path = QDir::cleanPath(parts.first() + QLatin1String("/") + name);
+
+                bool exist = false;
+                QList<QSharedPointer<Chart> > cfs = m_drawing->workbook->chartFiles();
+                for (int i=0; i<cfs.size(); ++i) {
+                    if (cfs[i]->filePath() == path) {
+                        //already exist
+                        exist = true;
+                        m_chartFile = cfs[i];
+                    }
+                }
+                if (!exist) {
+                    m_chartFile = QSharedPointer<Chart> (new Chart(m_drawing->sheet, Chart::F_LoadFromExists));
+                    m_chartFile->setFilePath(path);
+                    m_drawing->workbook->addChartFile(m_chartFile);
+                }
+            }
+        } else if (reader.tokenType() == QXmlStreamReader::EndElement
+                   && reader.name() == QLatin1String("graphicFrame")) {
+            break;
+        }
+    }
+
+    return;
+}
+
+void DrawingAnchor::loadXmlObjectGroupShape(QXmlStreamReader &reader)
+{
+    Q_UNUSED(reader)
+}
+
+void DrawingAnchor::loadXmlObjectPicture(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("pic"));
+
+    while (!reader.atEnd()) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("blip")) {
+                QString rId = reader.attributes().value(QLatin1String("r:embed")).toString();
+                QString name = m_drawing->relationships()->getRelationshipById(rId).target;
+
+                const auto parts = splitPath(m_drawing->filePath());
+                QString path = QDir::cleanPath(parts.first() + QLatin1String("/") + name);
+
+                bool exist = false;
+                const auto mfs = m_drawing->workbook->mediaFiles();
+                for (const auto &mf : mfs) {
+                    if (mf->fileName() == path) {
+                        //already exist
+                        exist = true;
+                        m_pictureFile = mf;
+                    }
+                }
+                if (!exist) {
+                    m_pictureFile = std::make_shared<MediaFile>(path);
+                    m_drawing->workbook->addMediaFile(m_pictureFile, true);
+                }
+            }
+        } else if (reader.tokenType() == QXmlStreamReader::EndElement
+                   && reader.name() == QLatin1String("pic")) {
+            break;
+        }
+    }
+
+    return;
+}
+
+void DrawingAnchor::loadXmlObjectShape(QXmlStreamReader &reader)
+{
+    /*
+    <xsd:complexType name="CT_Shape">
+        <xsd:sequence>
+            <xsd:element name="nvSpPr" type="CT_ShapeNonVisual" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
+            <xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="txBody" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
+        </xsd:sequence>
+        <xsd:attribute name="macro" type="xsd:string" use="optional"/>
+        <xsd:attribute name="textlink" type="xsd:string" use="optional"/>
+        <xsd:attribute name="fLocksText" type="xsd:boolean" use="optional" default="true"/>
+        <xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
+    </xsd:complexType>
+    */
+    /*
+    <xsd:complexType name="CT_ShapeNonVisual">
+        <xsd:sequence>
+        <xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
+        <xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1" maxOccurs="1"/>
+        </xsd:sequence>
+    </xsd:complexType>
+    */
+
+    Q_ASSERT(reader.name() == QLatin1String("sp"));
+
+    while (!reader.atEnd())
+    {
+        reader.readNextStartElement();
+
+        // qDebug() << __FUNCTION__ << reader.name().toString();
+
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            if (reader.name() == QLatin1String("nvSpPr"))
+            {
+
+            }
+            else if (reader.name() == QLatin1String("spPr"))
+            {
+
+            }
+            else if (reader.name() == QLatin1String("style"))
+            {
+
+            }
+            else if (reader.name() == QLatin1String("txBody"))
+            {
+
+            }
+        }
+        else if (reader.tokenType() == QXmlStreamReader::EndElement
+                   && reader.name() == QLatin1String("sp"))
+        {
+            break;
+        }
+    }
+
+    /*
+
+    bool hasoffext = false;
+    while (!reader.atEnd())
+    {
+        reader.readNextStartElement();
+
+        // qDebug() << __FUNCTION__ << reader.name().toString();
+
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            if (reader.name() == QLatin1String("blip"))
+            {
+                QString rId;
+                sp_blip_rembed= reader.attributes().value(QLatin1String("r:embed")).toString();
+                sp_blip_cstate=reader.attributes().value(QLatin1String("cstate")).toString();
+                rId=sp_blip_rembed;
+                QString name = m_drawing->relationships()->getRelationshipById(rId).target;
+                QString path = QDir::cleanPath(splitPath(m_drawing->filePath())[0] + QLatin1String("/") + name);
+                   bool exist = false;
+                   QList<QSharedPointer<MediaFile> > mfs = m_drawing->workbook->mediaFiles();
+                   for (int i=0; i<mfs.size(); ++i)
+                   {
+                       if (mfs[i]->fileName() == path)
+                       {
+                           //already exist
+                           exist = true;
+                           m_pictureFile = mfs[i];
+                       }
+                   }
+                   if (!exist) {
+                       m_pictureFile = QSharedPointer<MediaFile> (new MediaFile(path));
+                       m_drawing->workbook->addMediaFile(m_pictureFile, true);
+                   }
+            }
+            else if (reader.name() == QLatin1String("off"))
+            {
+               posTA = loadXmlPos(reader);
+               hasoffext=true;
+            }
+            else if (reader.name() == QLatin1String("ext")&&hasoffext)
+            {
+               extTA = loadXmlExt(reader);
+               hasoffext=false;
+            }
+            else if(reader.name() == QLatin1String("blipFill"))
+            {
+                // dev24 : fixed for old Qt 5
+
+                rotWithShapeTA = reader.attributes().value(QLatin1String("rotWithShape")).toString().toInt();
+                dpiTA = reader.attributes().value(QLatin1String("dpi")).toString().toInt();
+
+                // rotWithShapeTA = reader.attributes().value(QLatin1String("rotWithShape")).toInt();
+                // dpiTA = reader.attributes().value(QLatin1String("dpi")).toInt();
+
+            }else if(reader.name() == QLatin1String("cNvPr"))
+            {
+               xsp_cNvPR_name= reader.attributes().value(QLatin1String("name")).toString();
+               xsp_cNvPR_id= reader.attributes().value(QLatin1String("id")).toString();
+            }
+            else if(reader.name() == QLatin1String("spPr"))
+            {
+                xbwMode= reader.attributes().value(QLatin1String("bwMode")).toString();
+            }
+            else if(reader.name() == QLatin1String("prstGeom"))
+            {
+                xprstGeom_prst= reader.attributes().value(QLatin1String("prst")).toString();
+            }
+            else if(reader.name() == QLatin1String("ln"))
+            {
+                xIn_algn= reader.attributes().value(QLatin1String("algn")).toString();
+                xIn_cmpd= reader.attributes().value(QLatin1String("cmpd")).toString();
+                xIn_cap= reader.attributes().value(QLatin1String("cap")).toString();
+                xIn_w= reader.attributes().value(QLatin1String("w")).toString();
+            }
+            else if(reader.name() == QLatin1String("headEnd"))
+            {
+                x_headEnd_w= reader.attributes().value(QLatin1String("w")).toString();
+                x_headEnd_len= reader.attributes().value(QLatin1String("len")).toString();
+                x_headEnd_tyep= reader.attributes().value(QLatin1String("type")).toString();
+            }
+            else if(reader.name() == QLatin1String("tailEnd"))
+            {
+                x_tailEnd_w= reader.attributes().value(QLatin1String("w")).toString();
+                x_tailEnd_len= reader.attributes().value(QLatin1String("len")).toString();
+                x_tailEnd_tyep= reader.attributes().value(QLatin1String("type")).toString();
+            }
+            else if(reader.name() == QLatin1String("lnRef"))
+            {
+                Style_inref_idx= reader.attributes().value(QLatin1String("idx")).toString().trimmed();
+                reader.readNextStartElement();
+                if (reader.tokenType() == QXmlStreamReader::StartElement) {
+                    if(reader.name() == QLatin1String("schemeClr")){
+                        Style_inref_val=reader.attributes().value(QLatin1String("val")).toString().trimmed();
+                    }
+                }
+            }
+            else if(reader.name() == QLatin1String("fillRef"))
+            {
+                style_fillref_idx= reader.attributes().value(QLatin1String("idx")).toString().trimmed();
+                reader.readNextStartElement();
+                if (reader.tokenType() == QXmlStreamReader::StartElement)
+                {
+                    if(reader.name() == QLatin1String("schemeClr"))
+                    {
+                       style_fillref_val=reader.attributes().value(QLatin1String("val")).toString().trimmed();
+                    }
+                }
+            }
+            else if(reader.name() == QLatin1String("effectRef"))
+            {
+                style_effectref_idx= reader.attributes().value(QLatin1String("idx")).toString().trimmed();
+                reader.readNextStartElement();
+                if (reader.tokenType() == QXmlStreamReader::StartElement) {
+                    if(reader.name() == QLatin1String("schemeClr")){
+                      style_effectref_val=reader.attributes().value(QLatin1String("val")).toString().trimmed();
+                    }
+                }
+            }
+            else if(reader.name() == QLatin1String("fontRef"))
+            {
+                style_forntref_idx= reader.attributes().value(QLatin1String("idx")).toString().trimmed();
+                reader.readNextStartElement();
+                if (reader.tokenType() == QXmlStreamReader::StartElement) {
+                    if(reader.name() == QLatin1String("schemeClr")){
+                        style_forntref_val=reader.attributes().value(QLatin1String("val")).toString().trimmed();
+                    }
+                }
+            }
+
+        }
+        else if (reader.tokenType() == QXmlStreamReader::EndElement
+                   && reader.name() == QLatin1String("sp"))
+        {
+            break;
+        }
+    }
+
+    //*/
+
+    return;
+}
+
+void DrawingAnchor::saveXmlPos(QXmlStreamWriter &writer, const QPoint &pos) const
+{
+    writer.writeEmptyElement(QStringLiteral("xdr:pos"));
+    writer.writeAttribute(QStringLiteral("x"), QString::number(pos.x()));
+    writer.writeAttribute(QStringLiteral("y"), QString::number(pos.y()));
+}
+
+void DrawingAnchor::saveXmlExt(QXmlStreamWriter &writer, const QSize &ext) const
+{
+    writer.writeStartElement(QStringLiteral("xdr:ext"));
+    writer.writeAttribute(QStringLiteral("cx"), QString::number(ext.width()));
+    writer.writeAttribute(QStringLiteral("cy"), QString::number(ext.height()));
+    writer.writeEndElement(); //xdr:ext
+}
+
+void DrawingAnchor::saveXmlMarker(QXmlStreamWriter &writer, const XlsxMarker &marker, const QString &node) const
+{
+    writer.writeStartElement(node); //xdr:from or xdr:to
+    writer.writeTextElement(QStringLiteral("xdr:col"), QString::number(marker.col()));
+    writer.writeTextElement(QStringLiteral("xdr:colOff"), QString::number(marker.colOff()));
+    writer.writeTextElement(QStringLiteral("xdr:row"), QString::number(marker.row()));
+    writer.writeTextElement(QStringLiteral("xdr:rowOff"), QString::number(marker.rowOff()));
+    writer.writeEndElement();
+}
+
+void DrawingAnchor::saveXmlObject(QXmlStreamWriter &writer) const
+{
+    if (m_objectType == Picture)
+        saveXmlObjectPicture(writer);
+    else if (m_objectType == ConnectionShape)
+        saveXmlObjectConnectionShape(writer);
+    else if (m_objectType == GraphicFrame)
+        saveXmlObjectGraphicFrame(writer);
+    else if (m_objectType == GroupShape)
+        saveXmlObjectGroupShape(writer);
+    else if (m_objectType == Shape)
+        saveXmlObjectShape(writer);
+}
+
+void DrawingAnchor::saveXmlObjectConnectionShape(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("xdr:cxnSp"));  ///?
+    writer.writeAttribute(QStringLiteral("macro"), cxnSp_macro);
+
+        writer.writeStartElement(QStringLiteral("xdr:nvCxnSpPr"));
+           writer.writeEmptyElement(QStringLiteral("xdr:cNvPr"));
+           writer.writeAttribute(QStringLiteral("id"), xsp_cNvPR_id);
+           writer.writeAttribute(QStringLiteral("name"), xsp_cNvPR_name);
+           writer.writeEmptyElement(QStringLiteral("xdr:cNvCxnSpPr"));
+        writer.writeEndElement(); //xdr:nvCxnSpPr
+
+    writer.writeStartElement(QStringLiteral("xdr:spPr"));
+    if(!xbwMode.isNull()){
+         writer.writeAttribute(QStringLiteral("bwMode"), xbwMode);
+    }
+
+        writer.writeStartElement(QStringLiteral("a:xfrm"));
+        if(!cxnSp_filpV.isEmpty()){
+        writer.writeAttribute(QStringLiteral("flipV"), cxnSp_filpV);}
+        writer.writeEmptyElement(QStringLiteral("a:off"));
+        writer.writeAttribute(QStringLiteral("x"), QString::number(posTA.x()));
+        writer.writeAttribute(QStringLiteral("y"), QString::number(posTA.y()));
+        writer.writeEmptyElement(QStringLiteral("a:ext"));
+        writer.writeAttribute(QStringLiteral("cx"), QString::number(extTA.width()));
+        writer.writeAttribute(QStringLiteral("cy"), QString::number(extTA.height()));
+        writer.writeEndElement(); //a:xfrm
+
+        writer.writeStartElement(QStringLiteral("a:prstGeom"));
+        writer.writeAttribute(QStringLiteral("prst"), xprstGeom_prst);
+        writer.writeEmptyElement(QStringLiteral("a:avLst"));
+        writer.writeEndElement(); //a:prstGeom
+
+
+         writer.writeStartElement(QStringLiteral("a:ln"));
+            if(!xIn_w.isEmpty()&&!xIn_cap.isEmpty()){
+                if(!xIn_w.isEmpty()){
+                    writer.writeAttribute(QStringLiteral("w"), xIn_w);
+                }
+                if(!xIn_cap.isEmpty()){
+                    writer.writeAttribute(QStringLiteral("cap"), xIn_cap);
+                }
+                if(!xIn_cmpd.isEmpty()){
+                    writer.writeAttribute(QStringLiteral("cmpd"), xIn_cmpd);
+                }
+                if(!xIn_algn.isEmpty()){
+                    writer.writeAttribute(QStringLiteral("algn"), xIn_algn);
+                }
+            }
+             if((!x_headEnd_tyep.isEmpty())||(!x_headEnd_w.isEmpty())||(!x_headEnd_len.isEmpty())){
+                 writer.writeEmptyElement(QStringLiteral("a:headEnd"));
+                 if(!x_headEnd_tyep.isEmpty()){
+                    writer.writeAttribute(QStringLiteral("type"),x_headEnd_tyep);
+                 }
+                 if(!x_headEnd_w.isEmpty()){
+                   writer.writeAttribute(QStringLiteral("w"),x_headEnd_w);
+                 }
+                 if(!x_headEnd_len.isEmpty()){
+                   writer.writeAttribute(QStringLiteral("len"),x_headEnd_len);
+                 }
+             }
+             if((!x_tailEnd_tyep.isEmpty())||(!x_tailEnd_w.isEmpty())||(!x_tailEnd_len.isEmpty())){
+                  writer.writeEmptyElement(QStringLiteral("a:tailEnd"));
+                  if(!x_tailEnd_tyep.isEmpty()){
+                      writer.writeAttribute(QStringLiteral("type"),x_tailEnd_tyep);}
+                  if(!x_tailEnd_w.isEmpty()){
+                      writer.writeAttribute(QStringLiteral("w"),x_tailEnd_w);}
+                  if(!x_tailEnd_len.isEmpty()){
+                      writer.writeAttribute(QStringLiteral("len"),x_tailEnd_len);}
+              }
+
+         writer.writeEndElement();//a:ln
+
+
+      writer.writeEndElement(); //xdr:spPr
+      // writer style
+
+      writer.writeStartElement(QStringLiteral("xdr:style"));// style
+             writer.writeStartElement(QStringLiteral("a:lnRef"));//lnRef
+             writer.writeAttribute(QStringLiteral("idx"),Style_inref_idx);
+                writer.writeStartElement(QStringLiteral("a:schemeClr"));//val
+                writer.writeAttribute(QStringLiteral("val"),Style_inref_val);
+                writer.writeEndElement(); // val
+             writer.writeEndElement(); // lnRef
+             writer.writeStartElement(QStringLiteral("a:fillRef"));//fillRef
+             writer.writeAttribute(QStringLiteral("idx"),style_fillref_idx);
+                writer.writeStartElement(QStringLiteral("a:schemeClr"));//val
+                writer.writeAttribute(QStringLiteral("val"),style_fillref_val);
+                writer.writeEndElement(); // val
+             writer.writeEndElement(); // fillRef
+             writer.writeStartElement(QStringLiteral("a:effectRef"));//effectRef
+             writer.writeAttribute(QStringLiteral("idx"),style_effectref_idx);
+                writer.writeStartElement(QStringLiteral("a:schemeClr"));//val
+                writer.writeAttribute(QStringLiteral("val"),style_effectref_val);
+                writer.writeEndElement(); // val
+             writer.writeEndElement(); // effectRef
+             writer.writeStartElement(QStringLiteral("a:fontRef"));//fontRef
+             writer.writeAttribute(QStringLiteral("idx"),style_forntref_idx);
+                writer.writeStartElement(QStringLiteral("a:schemeClr"));//val
+                writer.writeAttribute(QStringLiteral("val"),style_forntref_val);
+                writer.writeEndElement(); // val
+             writer.writeEndElement(); // fontRef
+      writer.writeEndElement(); // style
+
+      writer.writeEndElement(); //xdr:sp
+}
+
+void DrawingAnchor::saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("xdr:graphicFrame"));
+    writer.writeAttribute(QStringLiteral("macro"), QString());
+
+    writer.writeStartElement(QStringLiteral("xdr:nvGraphicFramePr"));
+    writer.writeEmptyElement(QStringLiteral("xdr:cNvPr"));
+    writer.writeAttribute(QStringLiteral("id"), QString::number(m_id));
+    writer.writeAttribute(QStringLiteral("name"), QStringLiteral("Chart %1").arg(m_id));
+    writer.writeEmptyElement(QStringLiteral("xdr:cNvGraphicFramePr"));
+    writer.writeEndElement();//xdr:nvGraphicFramePr
+
+    writer.writeStartElement(QStringLiteral("xdr:xfrm"));
+    writer.writeEndElement(); //xdr:xfrm
+
+    writer.writeStartElement(QStringLiteral("a:graphic"));
+    writer.writeStartElement(QStringLiteral("a:graphicData"));
+    writer.writeAttribute(QStringLiteral("uri"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart"));
+
+    int idx = m_drawing->workbook->chartFiles().indexOf(m_chartFile);
+    m_drawing->relationships()->addDocumentRelationship(QStringLiteral("/chart"), QStringLiteral("../charts/chart%1.xml").arg(idx+1));
+
+    writer.writeEmptyElement(QStringLiteral("c:chart"));
+    writer.writeAttribute(QStringLiteral("xmlns:c"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart"));
+    writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
+    writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(m_drawing->relationships()->count()));
+
+    writer.writeEndElement(); //a:graphicData
+    writer.writeEndElement(); //a:graphic
+    writer.writeEndElement(); //xdr:graphicFrame
+}
+
+void DrawingAnchor::saveXmlObjectGroupShape(QXmlStreamWriter &writer) const
+{
+    Q_UNUSED(writer)
+}
+
+void DrawingAnchor::saveXmlObjectPicture(QXmlStreamWriter &writer) const
+{
+    Q_ASSERT(m_objectType == Picture && m_pictureFile);
+
+    writer.writeStartElement(QStringLiteral("xdr:pic"));
+
+    writer.writeStartElement(QStringLiteral("xdr:nvPicPr"));
+    writer.writeEmptyElement(QStringLiteral("xdr:cNvPr"));
+    writer.writeAttribute(QStringLiteral("id"), QString::number(m_id+1)); // liufeijin
+    writer.writeAttribute(QStringLiteral("name"), QStringLiteral("Picture %1").arg(m_id));
+
+    writer.writeStartElement(QStringLiteral("xdr:cNvPicPr"));
+    writer.writeEmptyElement(QStringLiteral("a:picLocks"));
+    writer.writeAttribute(QStringLiteral("noChangeAspect"), QStringLiteral("1"));
+    writer.writeEndElement(); //xdr:cNvPicPr
+
+    writer.writeEndElement(); //xdr:nvPicPr
+
+    m_drawing->relationships()->addDocumentRelationship(QStringLiteral("/image"), QStringLiteral("../media/image%1.%2")
+                                                     .arg(m_pictureFile->index()+1)
+                                                     .arg(m_pictureFile->suffix()));
+
+    writer.writeStartElement(QStringLiteral("xdr:blipFill"));
+    writer.writeEmptyElement(QStringLiteral("a:blip"));
+    writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
+    writer.writeAttribute(QStringLiteral("r:embed"), QStringLiteral("rId%1").arg(m_drawing->relationships()->count()));
+    writer.writeStartElement(QStringLiteral("a:stretch"));
+    writer.writeEmptyElement(QStringLiteral("a:fillRect"));
+    writer.writeEndElement(); //a:stretch
+    writer.writeEndElement();//xdr:blipFill
+
+    writer.writeStartElement(QStringLiteral("xdr:spPr"));
+
+    writer.writeStartElement(QStringLiteral("a:prstGeom"));
+    writer.writeAttribute(QStringLiteral("prst"), QStringLiteral("rect"));
+    writer.writeEmptyElement(QStringLiteral("a:avLst"));
+    writer.writeEndElement(); //a:prstGeom
+
+    writer.writeEndElement(); //xdr:spPr
+
+    writer.writeEndElement(); //xdr:pic
+}
+
+int DrawingAnchor::getm_id()
+{
+    return (this->m_id);
+}
+
+void DrawingAnchor::saveXmlObjectShape(QXmlStreamWriter &writer) const
+{
+//{{ liufeijin
+    writer.writeStartElement(QStringLiteral("xdr:sp"));  //xdr:sp
+        writer.writeAttribute(QStringLiteral("macro"), sp_macro);
+        writer.writeAttribute(QStringLiteral("textlink"),sp_textlink);
+
+    writer.writeStartElement(QStringLiteral("xdr:nvSpPr"));//xdr:nvSpPr
+
+           writer.writeStartElement(QStringLiteral("xdr:cNvPr"));
+              writer.writeAttribute(QStringLiteral("id"), xsp_cNvPR_id);
+              writer.writeAttribute(QStringLiteral("name"), xsp_cNvPR_name);
+              writer.writeStartElement(QStringLiteral("a:extLst"));
+              writer.writeEndElement();
+           writer.writeEndElement();//xdr:cNvPr
+
+          writer.writeEmptyElement(QStringLiteral("xdr:cNvSpPr"));
+
+    writer.writeEndElement(); //xdr:nvSpPr
+
+    writer.writeStartElement(QStringLiteral("xdr:spPr"));
+    if(!xbwMode.isNull()){
+         writer.writeAttribute(QStringLiteral("bwMode"), xbwMode);
+    }
+        writer.writeStartElement(QStringLiteral("a:xfrm"));
+        writer.writeEmptyElement(QStringLiteral("a:off"));
+        writer.writeAttribute(QStringLiteral("x"), QString::number(posTA.x()));
+        writer.writeAttribute(QStringLiteral("y"), QString::number(posTA.y()));
+        writer.writeEmptyElement(QStringLiteral("a:ext"));
+        writer.writeAttribute(QStringLiteral("cx"), QString::number(extTA.width()));
+        writer.writeAttribute(QStringLiteral("cy"), QString::number(extTA.height()));
+        writer.writeEndElement(); //a:xfrm
+
+        writer.writeStartElement(QStringLiteral("a:prstGeom"));
+        writer.writeAttribute(QStringLiteral("prst"), xprstGeom_prst);
+        writer.writeEmptyElement(QStringLiteral("a:avLst"));
+        writer.writeEndElement(); //a:prstGeom
+
+    if(m_pictureFile){
+        m_drawing->relationships()->addDocumentRelationship(QStringLiteral("/image"), QStringLiteral("../media/image%1.%2").arg(m_pictureFile->index()+1).arg(m_pictureFile->suffix()));
+        writer.writeStartElement(QStringLiteral("a:blipFill"));
+        writer.writeAttribute(QStringLiteral("dpi"), QString::number(dpiTA));
+        writer.writeAttribute(QStringLiteral("rotWithShape"),QString::number(rotWithShapeTA));
+
+         writer.writeStartElement(QStringLiteral("a:blip"));
+           writer.writeAttribute(QStringLiteral("r:embed"), QStringLiteral("rId%1").arg(m_drawing->relationships()->count()));  //sp_blip_rembed  QStringLiteral("rId%1").arg(m_drawing->relationships()->count()) can't made new pic
+           writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
+           if(!sp_blip_cstate.isNull()){
+             writer.writeAttribute(QStringLiteral("cstate"), sp_blip_cstate);
+           }
+          writer.writeEndElement();//a:blip
+             writer.writeEmptyElement(QStringLiteral("a:srcRect"));
+             writer.writeStartElement(QStringLiteral("a:stretch"));
+                    writer.writeEmptyElement(QStringLiteral("a:fillRect"));
+             writer.writeEndElement(); //a:stretch
+         writer.writeEndElement();//a:blipFill
+      }
+    writer.writeStartElement(QStringLiteral("a:ln"));
+       if(!xIn_w.isEmpty()&&!xIn_cap.isEmpty()){
+           if(!xIn_w.isEmpty()){
+               writer.writeAttribute(QStringLiteral("w"), xIn_w);
+           }
+           if(!xIn_cap.isEmpty()){
+               writer.writeAttribute(QStringLiteral("cap"), xIn_cap);
+           }
+           if(!xIn_cmpd.isEmpty()){
+               writer.writeAttribute(QStringLiteral("cmpd"), xIn_cmpd);
+           }
+           if(!xIn_algn.isEmpty()){
+               writer.writeAttribute(QStringLiteral("algn"), xIn_algn);
+           }
+       }
+        if((!x_headEnd_tyep.isEmpty())||(!x_headEnd_w.isEmpty())||(!x_headEnd_len.isEmpty())){
+            writer.writeEmptyElement(QStringLiteral("a:headEnd"));
+            if(!x_headEnd_tyep.isEmpty()){
+               writer.writeAttribute(QStringLiteral("type"),x_headEnd_tyep);
+            }
+            if(!x_headEnd_w.isEmpty()){
+              writer.writeAttribute(QStringLiteral("w"),x_headEnd_w);
+            }
+            if(!x_headEnd_len.isEmpty()){
+              writer.writeAttribute(QStringLiteral("len"),x_headEnd_len);
+            }
+        }
+        if((!x_tailEnd_tyep.isEmpty())||(!x_tailEnd_w.isEmpty())||(!x_tailEnd_len.isEmpty())){
+             writer.writeEmptyElement(QStringLiteral("a:tailEnd"));
+             if(!x_tailEnd_tyep.isEmpty()){
+                 writer.writeAttribute(QStringLiteral("type"),x_tailEnd_tyep);}
+             if(!x_tailEnd_w.isEmpty()){
+                 writer.writeAttribute(QStringLiteral("w"),x_tailEnd_w);}
+             if(!x_tailEnd_len.isEmpty()){
+                 writer.writeAttribute(QStringLiteral("len"),x_tailEnd_len);}
+         }
+
+    writer.writeEndElement();//a:ln
+
+
+ writer.writeEndElement(); //xdr:spPr
+ // writer style
+
+ writer.writeStartElement(QStringLiteral("xdr:style"));// style
+        writer.writeStartElement(QStringLiteral("a:lnRef"));//lnRef
+        writer.writeAttribute(QStringLiteral("idx"),Style_inref_idx);
+           writer.writeStartElement(QStringLiteral("a:schemeClr"));//val
+           writer.writeAttribute(QStringLiteral("val"),Style_inref_val);
+           writer.writeEndElement(); // val
+        writer.writeEndElement(); // lnRef
+        writer.writeStartElement(QStringLiteral("a:fillRef"));//fillRef
+        writer.writeAttribute(QStringLiteral("idx"),style_fillref_idx);
+           writer.writeStartElement(QStringLiteral("a:schemeClr"));//val
+           writer.writeAttribute(QStringLiteral("val"),style_fillref_val);
+           writer.writeEndElement(); // val
+        writer.writeEndElement(); // fillRef
+        writer.writeStartElement(QStringLiteral("a:effectRef"));//effectRef
+        writer.writeAttribute(QStringLiteral("idx"),style_effectref_idx);
+           writer.writeStartElement(QStringLiteral("a:schemeClr"));//val
+           writer.writeAttribute(QStringLiteral("val"),style_effectref_val);
+           writer.writeEndElement(); // val
+        writer.writeEndElement(); // effectRef
+        writer.writeStartElement(QStringLiteral("a:fontRef"));//fontRef
+        writer.writeAttribute(QStringLiteral("idx"),style_forntref_idx);
+           writer.writeStartElement(QStringLiteral("a:schemeClr"));//val
+           writer.writeAttribute(QStringLiteral("val"),style_forntref_val);
+           writer.writeEndElement(); // val
+        writer.writeEndElement(); // fontRef
+ writer.writeEndElement(); // style
+
+     writer.writeEndElement(); //xdr:sp
+
+	//}} liufeijin
+}
+
+//absolute anchor
+
+DrawingAbsoluteAnchor::DrawingAbsoluteAnchor(Drawing *drawing, ObjectType objectType)
+    :DrawingAnchor(drawing, objectType)
+{
+
+}
+
+// check point
+bool DrawingAbsoluteAnchor::loadFromXml(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("absoluteAnchor"));
+
+    while (!reader.atEnd()) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("pos"))
+            {
+                pos = loadXmlPos(reader);
+            }
+            else if (reader.name() == QLatin1String("ext"))
+            {
+                ext = loadXmlExt(reader);
+            }
+            else
+            {
+                loadXmlObject(reader);
+            }
+        }
+        else if (reader.tokenType() == QXmlStreamReader::EndElement
+                   && reader.name() == QLatin1String("absoluteAnchor"))
+        {
+            break;
+        }
+    }
+    return true;
+}
+
+void DrawingAbsoluteAnchor::saveToXml(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("xdr:absoluteAnchor"));
+    saveXmlPos(writer, pos);
+    saveXmlExt(writer, ext);
+
+    saveXmlObject(writer);
+
+    writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
+    writer.writeEndElement(); //xdr:absoluteAnchor
+}
+
+//one cell anchor
+
+DrawingOneCellAnchor::DrawingOneCellAnchor(Drawing *drawing, ObjectType objectType)
+    :DrawingAnchor(drawing, objectType)
+{
+
+}
+
+int DrawingOneCellAnchor::row() const
+{
+    return from.row();
+}
+
+int DrawingOneCellAnchor::col() const
+{
+    return from.col();
+}
+
+// check point
+bool DrawingOneCellAnchor::loadFromXml(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("oneCellAnchor"));
+
+    while (!reader.atEnd())
+    {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            if (reader.name() == QLatin1String("from"))
+            {
+                from = loadXmlMarker(reader, QLatin1String("from"));
+            }
+            else if (reader.name() == QLatin1String("ext"))
+            {
+                ext = loadXmlExt(reader);
+            }
+            else
+            {
+                loadXmlObject(reader);
+            }
+        }
+        else if (reader.tokenType() == QXmlStreamReader::EndElement
+                   && reader.name() == QLatin1String("oneCellAnchor"))
+        {
+            break;
+        }
+    }
+    return true;
+}
+
+void DrawingOneCellAnchor::saveToXml(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("xdr:oneCellAnchor"));
+
+    saveXmlMarker(writer, from, QStringLiteral("xdr:from"));
+    saveXmlExt(writer, ext);
+
+    saveXmlObject(writer);
+
+    writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
+    writer.writeEndElement(); //xdr:oneCellAnchor
+}
+
+/*
+   Two cell anchor
+
+   This class specifies a two cell anchor placeholder for a group
+   , a shape, or a drawing element. It moves with
+   cells and its extents are in EMU units.
+*/
+DrawingTwoCellAnchor::DrawingTwoCellAnchor(Drawing *drawing, ObjectType objectType)
+    :DrawingAnchor(drawing, objectType)
+{
+
+}
+
+int DrawingTwoCellAnchor::row() const
+{
+    return from.row();
+}
+
+int DrawingTwoCellAnchor::col() const
+{
+    return from.col();
+}
+
+// check point
+bool DrawingTwoCellAnchor::loadFromXml(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("twoCellAnchor"));
+
+    /*
+    <xsd:complexType name="CT_TwoCellAnchor">
+        <xsd:sequence>
+            <xsd:element name="from" type="CT_Marker"/>
+            <xsd:element name="to" type="CT_Marker"/>
+            <xsd:group ref="EG_ObjectChoices"/>
+            <xsd:element name="clientData" type="CT_AnchorClientData" minOccurs="1" maxOccurs="1"/>
+        </xsd:sequence>
+        <xsd:attribute name="editAs" type="ST_EditAs" use="optional" default="twoCell"/>
+    </xsd:complexType>
+    */
+
+	//{{ liufeijin
+	QXmlStreamAttributes attrs = reader.attributes();  // for absolute twocell aadd by liufeijin 20181024
+    editASName = attrs.value(QLatin1String("editAs")).toString();
+	//}}
+
+    while (!reader.atEnd())
+    {
+        reader.readNextStartElement();
+
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            if (reader.name() == QLatin1String("from"))
+            {
+                from = loadXmlMarker(reader, QLatin1String("from"));
+            }
+            else if (reader.name() == QLatin1String("to"))
+            {
+                to = loadXmlMarker(reader, QLatin1String("to"));
+            }
+            else if (reader.name() == QLatin1String("clientData"))
+            {
+                // clientData
+            }
+            else
+            {
+                /*
+                <xsd:group name="EG_ObjectChoices">
+                    <xsd:sequence>
+                        <xsd:choice minOccurs="1" maxOccurs="1">
+                            <xsd:element name="sp" type="CT_Shape"/>
+                            <xsd:element name="grpSp" type="CT_GroupShape"/>
+                            <xsd:element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
+                            <xsd:element name="cxnSp" type="CT_Connector"/>
+                            <xsd:element name="pic" type="CT_Picture"/>
+                            <xsd:element name="contentPart" type="CT_Rel"/>
+                        </xsd:choice>
+                    </xsd:sequence>
+                </xsd:group>
+                */
+
+                loadXmlObject(reader);
+            }
+        }
+        else if (reader.tokenType() == QXmlStreamReader::EndElement
+                   && reader.name() == QLatin1String("twoCellAnchor"))
+        {
+            break;
+        }
+    }
+    return true;
+}
+
+
+   void DrawingTwoCellAnchor::saveToXml(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("xdr:twoCellAnchor"));
+
+	//{{ liufeijin
+    // writer.writeAttribute(QStringLiteral("editAs"), QStringLiteral("oneCell"));
+   if(!editASName.isNull()){
+       writer.writeAttribute(QStringLiteral("editAs"), editASName ); //QStringLiteral("oneCell")
+   }
+	// }}
+
+    saveXmlMarker(writer, from, QStringLiteral("xdr:from"));
+    saveXmlMarker(writer, to, QStringLiteral("xdr:to"));
+
+    saveXmlObject(writer);
+
+    writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
+    writer.writeEndElement(); //xdr:twoCellAnchor
+
+}
+
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxformat.cpp b/internal_system_v1/QXlsx/source/xlsxformat.cpp
new file mode 100644
index 0000000..cc50677
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxformat.cpp
@@ -0,0 +1,1437 @@
+// xlsxformat.cpp
+
+#include <QtGlobal>
+#include <QDataStream>
+#include <QDebug>
+
+#include "xlsxformat.h"
+#include "xlsxformat_p.h"
+#include "xlsxcolor_p.h"
+#include "xlsxnumformatparser_p.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+FormatPrivate::FormatPrivate()
+	: dirty(true)
+	, font_dirty(true), font_index_valid(false), font_index(0)
+	, fill_dirty(true), fill_index_valid(false), fill_index(0)
+	, border_dirty(true), border_index_valid(false), border_index(0)
+	, xf_index(-1), xf_indexValid(false)
+	, is_dxf_fomat(false), dxf_index(-1), dxf_indexValid(false)
+	, theme(0)
+{
+}
+
+FormatPrivate::FormatPrivate(const FormatPrivate &other)
+	: QSharedData(other)
+	, dirty(other.dirty), formatKey(other.formatKey)
+	, font_dirty(other.font_dirty), font_index_valid(other.font_index_valid), font_key(other.font_key), font_index(other.font_index)
+	, fill_dirty(other.fill_dirty), fill_index_valid(other.fill_index_valid), fill_key(other.fill_key), fill_index(other.fill_index)
+	, border_dirty(other.border_dirty), border_index_valid(other.border_index_valid), border_key(other.border_key), border_index(other.border_index)
+	, xf_index(other.xf_index), xf_indexValid(other.xf_indexValid)
+	, is_dxf_fomat(other.is_dxf_fomat), dxf_index(other.dxf_index), dxf_indexValid(other.dxf_indexValid)
+	, theme(other.theme)
+	, properties(other.properties)
+{
+
+}
+
+FormatPrivate::~FormatPrivate()
+{
+
+}
+
+/*!
+ * \class Format
+ * \inmodule QtXlsx
+ * \brief Providing the methods and properties that are available for formatting cells in Excel.
+ */
+
+/*!
+ * \enum Format::FontScript
+ *
+ * The enum type defines the type of font script.
+ *
+ * \value FontScriptNormal normal
+ * \value FontScriptSuper super script
+ * \value FontScriptSub sub script
+ */
+
+
+/*!
+ * \enum Format::FontUnderline
+ *
+ * The enum type defines the type of font underline.
+ *
+ * \value FontUnderlineNone
+ * \value FontUnderlineSingle
+ * \value FontUnderlineDouble
+ * \value FontUnderlineSingleAccounting
+ * \value FontUnderlineDoubleAccounting
+ */
+
+/*!
+ * \enum Format::HorizontalAlignment
+ *
+ * The enum type defines the type of horizontal alignment.
+ *
+ * \value AlignHGeneral
+ * \value AlignLeft
+ * \value AlignHCenter
+ * \value AlignRight
+ * \value AlignHFill
+ * \value AlignHJustify
+ * \value AlignHMerge
+ * \value AlignHDistributed
+ */
+
+/*!
+ * \enum Format::VerticalAlignment
+ *
+ * The enum type defines the type of vertical alignment.
+ *
+ * \value AlignTop,
+ * \value AlignVCenter,
+ * \value AlignBottom,
+ * \value AlignVJustify,
+ * \value AlignVDistributed
+ */
+
+/*!
+ * \enum Format::BorderStyle
+ *
+ * The enum type defines the type of font underline.
+ *
+ * \value BorderNone
+ * \value BorderThin
+ * \value BorderMedium
+ * \value BorderDashed
+ * \value BorderDotted
+ * \value BorderThick
+ * \value BorderDouble
+ * \value BorderHair
+ * \value BorderMediumDashed
+ * \value BorderDashDot
+ * \value BorderMediumDashDot
+ * \value BorderDashDotDot
+ * \value BorderMediumDashDotDot
+ * \value BorderSlantDashDot
+*/
+
+/*!
+ * \enum Format::DiagonalBorderType
+ *
+ * The enum type defines the type of diagonal border.
+ *
+ * \value DiagonalBorderNone
+ * \value DiagonalBorderDown
+ * \value DiagonalBorderUp
+ * \value DiagnoalBorderBoth
+ */
+
+/*!
+ * \enum Format::FillPattern
+ *
+ * The enum type defines the type of fill.
+ *
+ * \value PatternNone
+ * \value PatternSolid
+ * \value PatternMediumGray
+ * \value PatternDarkGray
+ * \value PatternLightGray
+ * \value PatternDarkHorizontal
+ * \value PatternDarkVertical
+ * \value PatternDarkDown
+ * \value PatternDarkUp
+ * \value PatternDarkGrid
+ * \value PatternDarkTrellis
+ * \value PatternLightHorizontal
+ * \value PatternLightVertical
+ * \value PatternLightDown
+ * \value PatternLightUp
+ * \value PatternLightTrellis
+ * \value PatternGray125
+ * \value PatternGray0625
+ * \value PatternLightGrid
+ */
+
+/*!
+ *  Creates a new invalid format.
+ */
+Format::Format()
+{
+	//The d pointer is initialized with a null pointer
+}
+
+/*!
+   Creates a new format with the same attributes as the \a other format.
+ */
+Format::Format(const Format &other)
+	:d(other.d)
+{
+
+}
+
+/*!
+   Assigns the \a other format to this format, and returns a
+   reference to this format.
+ */
+Format &Format::operator =(const Format &other)
+{
+	d = other.d;
+	return *this;
+}
+
+/*!
+ * Destroys this format.
+ */
+Format::~Format()
+{
+}
+
+/*!
+ * Returns the number format identifier.
+ */
+int Format::numberFormatIndex() const
+{
+	return intProperty(FormatPrivate::P_NumFmt_Id, 0);
+}
+
+/*!
+ * Set the number format identifier. The \a format
+ * must be a valid built-in number format identifier
+ * or the identifier of a custom number format.
+ */
+void Format::setNumberFormatIndex(int format)
+{
+	setProperty(FormatPrivate::P_NumFmt_Id, format);
+	clearProperty(FormatPrivate::P_NumFmt_FormatCode);
+}
+
+/*!
+ * Returns the number format string.
+ * \note for built-in number formats, this may
+ * return an empty string.
+ */
+QString Format::numberFormat() const
+{
+	return stringProperty(FormatPrivate::P_NumFmt_FormatCode);
+}
+
+/*!
+ * Set number \a format.
+ * http://office.microsoft.com/en-001/excel-help/create-a-custom-number-format-HP010342372.aspx
+ */
+void Format::setNumberFormat(const QString &format)
+{
+	if (format.isEmpty())
+		return;
+	setProperty(FormatPrivate::P_NumFmt_FormatCode, format);
+	clearProperty(FormatPrivate::P_NumFmt_Id); //numFmt id must be re-generated.
+}
+
+/*!
+ * Returns whether the number format is probably a dateTime or not
+ */
+bool Format::isDateTimeFormat() const
+{
+	//NOTICE:
+
+	if (hasProperty(FormatPrivate::P_NumFmt_FormatCode)) 
+	{
+		//Custom numFmt, so
+		//Gauss from the number string
+		return NumFormatParser::isDateTime(numberFormat());
+	} 
+	else if (hasProperty(FormatPrivate::P_NumFmt_Id))
+	{
+		//Non-custom numFmt
+		int idx = numberFormatIndex();
+
+		//Is built-in date time number id?
+		if ((idx >= 14 && idx <= 22) || (idx >= 45 && idx <= 47))
+			return true;
+
+		if ((idx >= 27 && idx <= 36) || (idx >= 50 && idx <= 58)) //Used in CHS\CHT\JPN\KOR
+			return true;
+	}
+
+	return false;
+}
+
+/*!
+	\internal
+	Set a custom num \a format with the given \a id.
+ */
+void Format::setNumberFormat(int id, const QString &format)
+{
+	setProperty(FormatPrivate::P_NumFmt_Id, id);
+	setProperty(FormatPrivate::P_NumFmt_FormatCode, format);
+}
+
+/*!
+	\internal
+	Called by styles to fix the numFmt
+ */
+void Format::fixNumberFormat(int id, const QString &format)
+{
+	setProperty(FormatPrivate::P_NumFmt_Id, id, 0, false);
+	setProperty(FormatPrivate::P_NumFmt_FormatCode, format, QString(), false);
+}
+
+/*!
+	\internal
+	Return true if the format has number format.
+ */
+bool Format::hasNumFmtData() const
+{
+	if (!d)
+		return false;
+
+    if ( hasProperty(FormatPrivate::P_NumFmt_Id) ||
+         hasProperty(FormatPrivate::P_NumFmt_FormatCode) )
+    {
+		return true;
+	}
+	return false;
+}
+
+/*!
+ * Return the size of the font in points.
+ */
+int Format::fontSize() const
+{
+	return intProperty(FormatPrivate::P_Font_Size);
+}
+
+/*!
+ * Set the \a size of the font in points.
+ */
+void Format::setFontSize(int size)
+{
+	setProperty(FormatPrivate::P_Font_Size, size, 0);
+}
+
+/*!
+ * Return whether the font is italic.
+ */
+bool Format::fontItalic() const
+{
+	return boolProperty(FormatPrivate::P_Font_Italic);
+}
+
+/*!
+ * Turn on/off the italic font based on \a italic.
+ */
+void Format::setFontItalic(bool italic)
+{
+	setProperty(FormatPrivate::P_Font_Italic, italic, false);
+}
+
+/*!
+ * Return whether the font is strikeout.
+ */
+bool Format::fontStrikeOut() const
+{
+	return boolProperty(FormatPrivate::P_Font_StrikeOut);
+}
+
+/*!
+ * Turn on/off the strikeOut font based on \a strikeOut.
+ */
+void Format::setFontStrikeOut(bool strikeOut)
+{
+	setProperty(FormatPrivate::P_Font_StrikeOut, strikeOut, false);
+}
+
+/*!
+ * Return the color of the font.
+ */
+QColor Format::fontColor() const
+{
+	if (hasProperty(FormatPrivate::P_Font_Color))
+		return colorProperty(FormatPrivate::P_Font_Color);
+	return QColor();
+}
+
+/*!
+ * Set the \a color of the font.
+ */
+void Format::setFontColor(const QColor &color)
+{
+	setProperty(FormatPrivate::P_Font_Color, XlsxColor(color), XlsxColor());
+}
+
+/*!
+ * Return whether the font is bold.
+ */
+bool Format::fontBold() const
+{
+	return boolProperty(FormatPrivate::P_Font_Bold);
+}
+
+/*!
+ * Turn on/off the bold font based on the given \a bold.
+ */
+void Format::setFontBold(bool bold)
+{
+	setProperty(FormatPrivate::P_Font_Bold, bold, false);
+}
+
+/*!
+ * Return the script style of the font.
+ */
+Format::FontScript Format::fontScript() const
+{
+	return static_cast<Format::FontScript>(intProperty(FormatPrivate::P_Font_Script));
+}
+
+/*!
+ * Set the script style of the font to \a script.
+ */
+void Format::setFontScript(FontScript script)
+{
+	setProperty(FormatPrivate::P_Font_Script, script, FontScriptNormal);
+}
+
+/*!
+ * Return the underline style of the font.
+ */
+Format::FontUnderline Format::fontUnderline() const
+{
+	return static_cast<Format::FontUnderline>(intProperty(FormatPrivate::P_Font_Underline));
+}
+
+/*!
+ * Set the underline style of the font to \a underline.
+ */
+void Format::setFontUnderline(FontUnderline underline)
+{
+	setProperty(FormatPrivate::P_Font_Underline, underline, FontUnderlineNone);
+}
+
+/*!
+ * Return whether the font is outline.
+ */
+bool Format::fontOutline() const
+{
+	return boolProperty(FormatPrivate::P_Font_Outline);
+}
+
+/*!
+ * Turn on/off the outline font based on \a outline.
+ */
+void Format::setFontOutline(bool outline)
+{
+	setProperty(FormatPrivate::P_Font_Outline, outline, false);
+}
+
+/*!
+ * Return the name of the font.
+ */
+QString Format::fontName() const
+{
+	return stringProperty(FormatPrivate::P_Font_Name, QStringLiteral("Calibri"));
+}
+
+/*!
+ * Set the name of the font to \a name.
+ */
+void Format::setFontName(const QString &name)
+{
+	setProperty(FormatPrivate::P_Font_Name, name, QStringLiteral("Calibri"));
+}
+
+/*!
+ * Returns a QFont object based on font data contained in the format.
+ */
+QFont Format::font() const
+{
+   QFont font;
+   font.setFamily(fontName());
+   if (fontSize() > 0)
+	   font.setPointSize(fontSize());
+   font.setBold(fontBold());
+   font.setItalic(fontItalic());
+   font.setUnderline(fontUnderline()!=FontUnderlineNone);
+   font.setStrikeOut(fontStrikeOut());
+   return font;
+}
+
+/*!
+ * Set the format properties from the given \a font.
+ */
+void Format::setFont(const QFont &font)
+{
+	setFontName(font.family());
+	if (font.pointSize() > 0)
+		setFontSize(font.pointSize());
+	setFontBold(font.bold());
+	setFontItalic(font.italic());
+	setFontUnderline(font.underline() ? FontUnderlineSingle : FontUnderlineNone);
+	setFontStrikeOut(font.strikeOut());
+}
+
+/*!
+ * \internal
+ * When the format has font data, when need to assign a valid index for it.
+ * The index value is depend on the order <fonts > in styles.xml
+ */
+bool Format::fontIndexValid() const
+{
+	if (!hasFontData())
+		return false;
+	return d->font_index_valid;
+}
+
+/*!
+ * \internal
+ */
+int Format::fontIndex() const
+{
+	if (fontIndexValid())
+		return d->font_index;
+
+	return 0;
+}
+
+/*!
+ * \internal
+ */
+void Format::setFontIndex(int index)
+{
+	d->font_index = index;
+	d->font_index_valid = true;
+}
+
+/*!
+ * \internal
+ */
+QByteArray Format::fontKey() const
+{
+	if (isEmpty())
+		return QByteArray();
+
+	if (d->font_dirty) {
+		QByteArray key;
+		QDataStream stream(&key, QIODevice::WriteOnly);
+		for (int i=FormatPrivate::P_Font_STARTID; i<FormatPrivate::P_Font_ENDID; ++i) {
+            auto it = d->properties.constFind(i);
+            if (it != d->properties.constEnd())
+                stream << i << it.value();
+		};
+
+		const_cast<Format*>(this)->d->font_key = key;
+		const_cast<Format*>(this)->d->font_dirty = false;
+	}
+
+	return d->font_key;
+}
+
+/*!
+	\internal
+	Return true if the format has font format, otherwise return false.
+ */
+bool Format::hasFontData() const
+{
+	if (!d)
+		return false;
+
+	for (int i=FormatPrivate::P_Font_STARTID; i<FormatPrivate::P_Font_ENDID; ++i) {
+		if (hasProperty(i))
+			return true;
+	}
+	return false;
+}
+
+/*!
+ * Return the horizontal alignment.
+ */
+Format::HorizontalAlignment Format::horizontalAlignment() const
+{
+	return static_cast<Format::HorizontalAlignment>(intProperty(FormatPrivate::P_Alignment_AlignH, AlignHGeneral));
+}
+
+/*!
+ * Set the horizontal alignment with the given \a align.
+ */
+void Format::setHorizontalAlignment(HorizontalAlignment align)
+{
+	if (hasProperty(FormatPrivate::P_Alignment_Indent)
+			&&(align != AlignHGeneral && align != AlignLeft && align != AlignRight && align != AlignHDistributed)) {
+		clearProperty(FormatPrivate::P_Alignment_Indent);
+	}
+
+	if (hasProperty(FormatPrivate::P_Alignment_ShinkToFit)
+			&& (align == AlignHFill || align == AlignHJustify || align == AlignHDistributed)) {
+		clearProperty(FormatPrivate::P_Alignment_ShinkToFit);
+	}
+
+	setProperty(FormatPrivate::P_Alignment_AlignH, align, AlignHGeneral);
+}
+
+/*!
+ * Return the vertical alignment.
+ */
+Format::VerticalAlignment Format::verticalAlignment() const
+{
+	return static_cast<Format::VerticalAlignment>(intProperty(FormatPrivate::P_Alignment_AlignV, AlignBottom));
+}
+
+/*!
+ * Set the vertical alignment with the given \a align.
+ */
+void Format::setVerticalAlignment(VerticalAlignment align)
+{
+	setProperty(FormatPrivate::P_Alignment_AlignV, align, AlignBottom);
+}
+
+/*!
+ * Return whether the cell text is wrapped.
+ */
+bool Format::textWrap() const
+{
+	return boolProperty(FormatPrivate::P_Alignment_Wrap);
+}
+
+/*!
+ * Enable the text wrap if \a wrap is true.
+ */
+void Format::setTextWrap(bool wrap)
+{
+	if (wrap && hasProperty(FormatPrivate::P_Alignment_ShinkToFit))
+		clearProperty(FormatPrivate::P_Alignment_ShinkToFit);
+
+	setProperty(FormatPrivate::P_Alignment_Wrap, wrap, false);
+}
+
+/*!
+ * Return the text rotation.
+ */
+int Format::rotation() const
+{
+	return intProperty(FormatPrivate::P_Alignment_Rotation);
+}
+
+/*!
+ * Set the text roation with the given \a rotation. Must be in the range [0, 180] or 255.
+ */
+void Format::setRotation(int rotation)
+{
+	setProperty(FormatPrivate::P_Alignment_Rotation, rotation, 0);
+}
+
+/*!
+ * Return the text indentation level.
+ */
+int Format::indent() const
+{
+	return intProperty(FormatPrivate::P_Alignment_Indent);
+}
+
+/*!
+ * Set the text indentation level with the given \a indent. Must be less than or equal to 15.
+ */
+void Format::setIndent(int indent)
+{
+	if (indent && hasProperty(FormatPrivate::P_Alignment_AlignH)) {
+		HorizontalAlignment hl = horizontalAlignment();
+
+		if (hl != AlignHGeneral && hl != AlignLeft && hl!= AlignRight && hl!= AlignHJustify) {
+			setHorizontalAlignment(AlignLeft);
+		}
+	}
+
+	setProperty(FormatPrivate::P_Alignment_Indent, indent, 0);
+}
+
+/*!
+ * Return whether the cell is shrink to fit.
+ */
+bool Format::shrinkToFit() const
+{
+	return boolProperty(FormatPrivate::P_Alignment_ShinkToFit);
+}
+
+/*!
+ * Turn on/off shrink to fit base on \a shink.
+ */
+void Format::setShrinkToFit(bool shink)
+{
+	if (shink && hasProperty(FormatPrivate::P_Alignment_Wrap))
+		clearProperty(FormatPrivate::P_Alignment_Wrap);
+
+	if (shink && hasProperty(FormatPrivate::P_Alignment_AlignH)) {
+		HorizontalAlignment hl = horizontalAlignment();
+		if (hl == AlignHFill || hl == AlignHJustify || hl == AlignHDistributed)
+			setHorizontalAlignment(AlignLeft);
+	}
+
+	setProperty(FormatPrivate::P_Alignment_ShinkToFit, shink, false);
+}
+
+/*!
+ * \internal
+ */
+bool Format::hasAlignmentData() const
+{
+	if (!d)
+		return false;
+
+	for (int i=FormatPrivate::P_Alignment_STARTID; i<FormatPrivate::P_Alignment_ENDID; ++i) {
+		if (hasProperty(i))
+			return true;
+	}
+	return false;
+}
+
+/*!
+ * Set the border style with the given \a style.
+ */
+void Format::setBorderStyle(BorderStyle style)
+{
+	setLeftBorderStyle(style);
+	setRightBorderStyle(style);
+	setBottomBorderStyle(style);
+	setTopBorderStyle(style);
+}
+
+/*!
+ * Sets the border color with the given \a color.
+ */
+void Format::setBorderColor(const QColor &color)
+{
+	setLeftBorderColor(color);
+	setRightBorderColor(color);
+	setTopBorderColor(color);
+	setBottomBorderColor(color);
+}
+
+/*!
+ * Returns the left border style
+ */
+Format::BorderStyle Format::leftBorderStyle() const
+{
+	return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_LeftStyle));
+}
+
+/*!
+ * Sets the left border style to \a style
+ */
+void Format::setLeftBorderStyle(BorderStyle style)
+{
+	setProperty(FormatPrivate::P_Border_LeftStyle, style, BorderNone);
+}
+
+/*!
+ * Returns the left border color
+ */
+QColor Format::leftBorderColor() const
+{
+	return colorProperty(FormatPrivate::P_Border_LeftColor);
+}
+
+/*!
+	Sets the left border color to the given \a color
+*/
+void Format::setLeftBorderColor(const QColor &color)
+{
+	setProperty(FormatPrivate::P_Border_LeftColor, XlsxColor(color), XlsxColor());
+}
+
+/*!
+	Returns the right border style.
+*/
+Format::BorderStyle Format::rightBorderStyle() const
+{
+	return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_RightStyle));
+}
+
+/*!
+	Sets the right border style to the given \a style.
+*/
+void Format::setRightBorderStyle(BorderStyle style)
+{
+	setProperty(FormatPrivate::P_Border_RightStyle, style, BorderNone);
+}
+
+/*!
+	Returns the right border color.
+*/
+QColor Format::rightBorderColor() const
+{
+	return colorProperty(FormatPrivate::P_Border_RightColor);
+}
+
+/*!
+	Sets the right border color to the given \a color
+*/
+void Format::setRightBorderColor(const QColor &color)
+{
+	setProperty(FormatPrivate::P_Border_RightColor, XlsxColor(color), XlsxColor());
+}
+
+/*!
+	Returns the top border style.
+*/
+Format::BorderStyle Format::topBorderStyle() const
+{
+	return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_TopStyle));
+}
+
+/*!
+	Sets the top border style to the given \a style.
+*/
+void Format::setTopBorderStyle(BorderStyle style)
+{
+	setProperty(FormatPrivate::P_Border_TopStyle, style, BorderNone);
+}
+
+/*!
+	Returns the top border color.
+*/
+QColor Format::topBorderColor() const
+{
+	return colorProperty(FormatPrivate::P_Border_TopColor);
+}
+
+/*!
+	Sets the top border color to the given \a color.
+*/
+void Format::setTopBorderColor(const QColor &color)
+{
+	setProperty(FormatPrivate::P_Border_TopColor, XlsxColor(color), XlsxColor());
+}
+
+/*!
+	Returns the bottom border style.
+*/
+Format::BorderStyle Format::bottomBorderStyle() const
+{
+	return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_BottomStyle));
+}
+
+/*!
+	Sets the bottom border style to the given \a style.
+*/
+void Format::setBottomBorderStyle(BorderStyle style)
+{
+	setProperty(FormatPrivate::P_Border_BottomStyle, style, BorderNone);
+}
+
+/*!
+	Returns the bottom border color.
+*/
+QColor Format::bottomBorderColor() const
+{
+	return colorProperty(FormatPrivate::P_Border_BottomColor);
+}
+
+/*!
+	Sets the bottom border color to the given \a color.
+*/
+void Format::setBottomBorderColor(const QColor &color)
+{
+	setProperty(FormatPrivate::P_Border_BottomColor, XlsxColor(color), XlsxColor());
+}
+
+/*!
+	Return the diagonla border style.
+*/
+Format::BorderStyle Format::diagonalBorderStyle() const
+{
+	return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_DiagonalStyle));
+}
+
+/*!
+	Sets the diagonal border style to the given \a style.
+*/
+void Format::setDiagonalBorderStyle(BorderStyle style)
+{
+	setProperty(FormatPrivate::P_Border_DiagonalStyle, style, BorderNone);
+}
+
+/*!
+	Returns the diagonal border type.
+*/
+Format::DiagonalBorderType Format::diagonalBorderType() const
+{
+	return static_cast<DiagonalBorderType>(intProperty(FormatPrivate::P_Border_DiagonalType));
+}
+
+/*!
+	Sets the diagonal border type to the given \a style
+*/
+void Format::setDiagonalBorderType(DiagonalBorderType style)
+{
+	setProperty(FormatPrivate::P_Border_DiagonalType, style, DiagonalBorderNone);
+}
+
+/*!
+	Returns the diagonal border color.
+*/
+QColor Format::diagonalBorderColor() const
+{
+	return colorProperty(FormatPrivate::P_Border_DiagonalColor);
+}
+
+/*!
+	Sets the diagonal border color to the given \a color
+*/
+void Format::setDiagonalBorderColor(const QColor &color)
+{
+	setProperty(FormatPrivate::P_Border_DiagonalColor, XlsxColor(color), XlsxColor());
+}
+
+/*!
+	\internal
+	Returns whether this format has been set valid border index.
+*/
+bool Format::borderIndexValid() const
+{
+	if (!hasBorderData())
+		return false;
+	return d->border_index_valid;
+}
+
+/*!
+	\internal
+	Returns the border index.
+*/
+int Format::borderIndex() const
+{
+	if (borderIndexValid())
+		return d->border_index;
+	return 0;
+}
+
+/*!
+ * \internal
+ */
+void Format::setBorderIndex(int index)
+{
+	d->border_index = index;
+	d->border_index_valid = true;
+}
+
+/*! \internal
+ */
+QByteArray Format::borderKey() const
+{
+	if (isEmpty())
+		return QByteArray();
+
+	if (d->border_dirty) {
+		QByteArray key;
+		QDataStream stream(&key, QIODevice::WriteOnly);
+		for (int i=FormatPrivate::P_Border_STARTID; i<FormatPrivate::P_Border_ENDID; ++i) {
+            auto it = d->properties.constFind(i);
+            if (it != d->properties.constEnd())
+                stream << i << it.value();
+		};
+
+		const_cast<Format*>(this)->d->border_key = key;
+		const_cast<Format*>(this)->d->border_dirty = false;
+	}
+
+	return d->border_key;
+}
+
+/*!
+	\internal
+	Return true if the format has border format, otherwise return false.
+ */
+bool Format::hasBorderData() const
+{
+	if (!d)
+		return false;
+
+	for (int i=FormatPrivate::P_Border_STARTID; i<FormatPrivate::P_Border_ENDID; ++i) {
+		if (hasProperty(i))
+			return true;
+	}
+	return false;
+}
+
+/*!
+	Return the fill pattern.
+*/
+Format::FillPattern Format::fillPattern() const
+{
+	return static_cast<FillPattern>(intProperty(FormatPrivate::P_Fill_Pattern, PatternNone));
+}
+
+/*!
+	Sets the fill pattern to the given \a pattern.
+*/
+void Format::setFillPattern(FillPattern pattern)
+{
+	setProperty(FormatPrivate::P_Fill_Pattern, pattern, PatternNone);
+}
+
+/*!
+	Returns the foreground color of the pattern.
+*/
+QColor Format::patternForegroundColor() const
+{
+	return colorProperty(FormatPrivate::P_Fill_FgColor);
+}
+
+/*!
+	Sets the foreground color of the pattern with the given \a color.
+*/
+void Format::setPatternForegroundColor(const QColor &color)
+{
+	if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern))
+		setFillPattern(PatternSolid);
+	setProperty(FormatPrivate::P_Fill_FgColor, XlsxColor(color), XlsxColor());
+}
+
+/*!
+	Returns the background color of the pattern.
+*/
+QColor Format::patternBackgroundColor() const
+{
+	return colorProperty(FormatPrivate::P_Fill_BgColor);
+}
+
+/*!
+	Sets the background color of the pattern with the given \a color.
+*/
+void Format::setPatternBackgroundColor(const QColor &color)
+{
+	if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern))
+		setFillPattern(PatternSolid);
+	setProperty(FormatPrivate::P_Fill_BgColor, XlsxColor(color), XlsxColor());
+}
+
+/*!
+ * \internal
+ */
+bool Format::fillIndexValid() const
+{
+	if (!hasFillData())
+		return false;
+	return d->fill_index_valid;
+}
+
+/*!
+ * \internal
+ */
+int Format::fillIndex() const
+{
+	if (fillIndexValid())
+		return d->fill_index;
+	return 0;
+}
+
+/*!
+ * \internal
+ */
+void Format::setFillIndex(int index)
+{
+	d->fill_index = index;
+	d->fill_index_valid = true;
+}
+
+/*!
+ * \internal
+ */
+QByteArray Format::fillKey() const
+{
+	if (isEmpty())
+		return QByteArray();
+
+	if (d->fill_dirty) {
+		QByteArray key;
+		QDataStream stream(&key, QIODevice::WriteOnly);
+		for (int i=FormatPrivate::P_Fill_STARTID; i<FormatPrivate::P_Fill_ENDID; ++i) {
+            auto it = d->properties.constFind(i);
+            if (it != d->properties.constEnd())
+                stream << i << it.value();
+		};
+
+		const_cast<Format*>(this)->d->fill_key = key;
+		const_cast<Format*>(this)->d->fill_dirty = false;
+	}
+
+	return d->fill_key;
+}
+
+/*!
+	\internal
+	Return true if the format has fill format, otherwise return false.
+ */
+bool Format::hasFillData() const
+{
+	if (!d)
+		return false;
+
+	for (int i=FormatPrivate::P_Fill_STARTID; i<FormatPrivate::P_Fill_ENDID; ++i) {
+		if (hasProperty(i))
+			return true;
+	}
+	return false;
+}
+
+/*!
+	Returns whether the hidden protection property is set to true.
+*/
+bool Format::hidden() const
+{
+	return boolProperty(FormatPrivate::P_Protection_Hidden);
+}
+
+/*!
+	Sets the hidden protection property with the given \a hidden.
+*/
+void Format::setHidden(bool hidden)
+{
+	setProperty(FormatPrivate::P_Protection_Hidden, hidden);
+}
+
+/*!
+	Returns whether the locked protection property is set to true.
+*/
+bool Format::locked() const
+{
+	return boolProperty(FormatPrivate::P_Protection_Locked);
+}
+
+/*!
+	Sets the locked protection property with the given \a locked.
+*/
+void Format::setLocked(bool locked)
+{
+	setProperty(FormatPrivate::P_Protection_Locked, locked);
+}
+
+/*!
+	\internal
+	Return true if the format has protection data, otherwise return false.
+ */
+bool Format::hasProtectionData() const
+{
+	if (!d)
+		return false;
+
+	if (hasProperty(FormatPrivate::P_Protection_Hidden)
+			|| hasProperty(FormatPrivate::P_Protection_Locked)) {
+		return true;
+	}
+	return false;
+}
+
+/*!
+	Merges the current format with the properties described by format \a modifier.
+ */
+void Format::mergeFormat(const Format &modifier)
+{
+	if (!modifier.isValid())
+		return;
+
+	if (!isValid()) {
+		d = modifier.d;
+		return;
+	}
+
+	QMapIterator<int, QVariant> it(modifier.d->properties);
+	while(it.hasNext()) {
+		it.next();
+		setProperty(it.key(), it.value());
+	}
+}
+
+/*!
+	Returns true if the format is valid; otherwise returns false.
+ */
+bool Format::isValid() const
+{
+	if (d)
+		return true;
+	return false;
+}
+
+/*!
+	Returns true if the format is empty; otherwise returns false.
+ */
+bool Format::isEmpty() const
+{
+	if (!d)
+		return true;
+	return d->properties.isEmpty();
+}
+
+/*!
+ * \internal
+ */
+QByteArray Format::formatKey() const
+{
+	if (isEmpty())
+		return QByteArray();
+
+	if (d->dirty) {
+		QByteArray key;
+		QDataStream stream(&key, QIODevice::WriteOnly);
+
+		QMapIterator<int, QVariant> i(d->properties);
+		while (i.hasNext()) {
+			i.next();
+			stream<<i.key()<<i.value();
+		}
+
+		d->formatKey = key;
+		d->dirty = false;
+	}
+
+	return d->formatKey;
+}
+
+/*!
+ * \internal
+ *  Called by QXlsx::Styles or some unittests.
+ */
+void Format::setXfIndex(int index)
+{
+	if (!d)
+		d = new FormatPrivate;
+	d->xf_index = index;
+	d->xf_indexValid = true;
+}
+
+/*!
+ * \internal
+ */
+int Format::xfIndex() const
+{
+	if (!d)
+		return -1;
+	return d->xf_index;
+}
+
+/*!
+ * \internal
+ */
+bool Format::xfIndexValid() const
+{
+	if (!d)
+		return false;
+	return d->xf_indexValid;
+}
+
+/*!
+ * \internal
+ *  Called by QXlsx::Styles or some unittests.
+ */
+void Format::setDxfIndex(int index)
+{
+	if (!d)
+		d = new FormatPrivate;
+	d->dxf_index = index;
+	d->dxf_indexValid = true;
+}
+
+/*!
+ * \internal
+ * Returns the index in the styles dxfs.
+ */
+int Format::dxfIndex() const
+{
+	if (!d)
+		return -1;
+	return d->dxf_index;
+}
+
+/*!
+ * \internal
+ * Returns whether the dxf index is valid or not.
+ */
+bool Format::dxfIndexValid() const
+{
+	if (!d)
+		return false;
+	return d->dxf_indexValid;
+}
+
+/*!
+	Returns ture if the \a format is equal to this format.
+*/
+bool Format::operator ==(const Format &format) const
+{
+	return this->formatKey() == format.formatKey();
+}
+
+/*!
+	Returns ture if the \a format is not equal to this format.
+*/
+bool Format::operator !=(const Format &format) const
+{
+	return this->formatKey() != format.formatKey();
+}
+
+int Format::theme() const
+{
+	return d->theme;
+}
+
+/*!
+ * \internal
+ */
+QVariant Format::property(int propertyId, const QVariant &defaultValue) const
+{
+    if (d) {
+        auto it = d->properties.constFind(propertyId);
+        if (it != d->properties.constEnd())
+            return it.value();
+    }
+	return defaultValue;
+}
+
+/*!
+ * \internal
+ */
+void Format::setProperty(int propertyId, const QVariant &value, const QVariant &clearValue, bool detach)
+{
+	if (!d)
+		d = new FormatPrivate;
+
+    if (value != clearValue)
+    {
+        auto it = d->properties.constFind(propertyId);
+        if (it != d->properties.constEnd() && it.value() == value)
+			return;
+
+		if (detach)
+			d.detach();
+
+		d->properties[propertyId] = value;
+    }
+    else
+    {
+		if (!d->properties.contains(propertyId))
+			return;
+
+		if (detach)
+			d.detach();
+
+		d->properties.remove(propertyId);
+	}
+
+	d->dirty = true;
+	d->xf_indexValid = false;
+	d->dxf_indexValid = false;
+
+    if (propertyId >= FormatPrivate::P_Font_STARTID && propertyId < FormatPrivate::P_Font_ENDID)
+    {
+		d->font_dirty = true;
+		d->font_index_valid = false;
+    }
+    else if (propertyId >= FormatPrivate::P_Border_STARTID && propertyId < FormatPrivate::P_Border_ENDID)
+    {
+		d->border_dirty = true;
+		d->border_index_valid = false;
+    }
+    else if (propertyId >= FormatPrivate::P_Fill_STARTID && propertyId < FormatPrivate::P_Fill_ENDID)
+    {
+		d->fill_dirty = true;
+		d->fill_index_valid = false;
+	}
+}
+
+/*!
+ * \internal
+ */
+void Format::clearProperty(int propertyId)
+{
+	setProperty(propertyId, QVariant());
+}
+
+/*!
+ * \internal
+ */
+bool Format::hasProperty(int propertyId) const
+{
+	if (!d)
+		return false;
+	return d->properties.contains(propertyId);
+}
+
+/*!
+ * \internal
+ */
+bool Format::boolProperty(int propertyId, bool defaultValue) const
+{
+	if (!hasProperty(propertyId))
+		return defaultValue;
+
+	const QVariant prop = d->properties[propertyId];
+	if (prop.userType() != QMetaType::Bool)
+		return defaultValue;
+	return prop.toBool();
+}
+
+/*!
+ * \internal
+ */
+int Format::intProperty(int propertyId, int defaultValue) const
+{
+	if (!hasProperty(propertyId))
+		return defaultValue;
+
+	const QVariant prop = d->properties[propertyId];
+	if (prop.userType() != QMetaType::Int)
+		return defaultValue;
+	return prop.toInt();
+}
+
+/*!
+ * \internal
+ */
+double Format::doubleProperty(int propertyId, double defaultValue) const
+{
+	if (!hasProperty(propertyId))
+		return defaultValue;
+
+	const QVariant prop = d->properties[propertyId];
+	if (prop.userType() != QMetaType::Double && prop.userType() != QMetaType::Float)
+		return defaultValue;
+	return prop.toDouble();
+}
+
+/*!
+ * \internal
+ */
+QString Format::stringProperty(int propertyId, const QString &defaultValue) const
+{
+	if (!hasProperty(propertyId))
+		return defaultValue;
+
+	const QVariant prop = d->properties[propertyId];
+	if (prop.userType() != QMetaType::QString)
+		return defaultValue;
+	return prop.toString();
+}
+
+/*!
+ * \internal
+ */
+QColor Format::colorProperty(int propertyId, const QColor &defaultValue) const
+{
+	if (!hasProperty(propertyId))
+		return defaultValue;
+
+	const QVariant prop = d->properties[propertyId];
+	if (prop.userType() != qMetaTypeId<XlsxColor>())
+		return defaultValue;
+	return qvariant_cast<XlsxColor>(prop).rgbColor();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const Format &f)
+{
+	dbg.nospace() << "QXlsx::Format(" << f.d->properties << ")";
+	return dbg.space();
+}
+#endif
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxmediafile.cpp b/internal_system_v1/QXlsx/source/xlsxmediafile.cpp
new file mode 100644
index 0000000..f9c6ce5
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxmediafile.cpp
@@ -0,0 +1,78 @@
+// xlsxmediafile.cpp
+
+#include <QtGlobal>
+#include <QCryptographicHash>
+
+#include "xlsxmediafile_p.h"
+
+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
diff --git a/internal_system_v1/QXlsx/source/xlsxnumformatparser.cpp b/internal_system_v1/QXlsx/source/xlsxnumformatparser.cpp
new file mode 100644
index 0000000..d00923a
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxnumformatparser.cpp
@@ -0,0 +1,74 @@
+// xlsxnumformatparser.cpp
+
+#include "xlsxnumformatparser_p.h"
+
+#include <QtGlobal>
+#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 && formatCode[++i] != QLatin1Char('"'))
+                ;
+            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
diff --git a/internal_system_v1/QXlsx/source/xlsxrelationships.cpp b/internal_system_v1/QXlsx/source/xlsxrelationships.cpp
new file mode 100644
index 0000000..f5c3282
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxrelationships.cpp
@@ -0,0 +1,169 @@
+// xlsxrelationships.cpp
+
+#include <QtGlobal>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QDir>
+#include <QFile>
+#include <QBuffer>
+
+#include "xlsxrelationships_p.h"
+
+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
diff --git a/internal_system_v1/QXlsx/source/xlsxrichstring.cpp b/internal_system_v1/QXlsx/source/xlsxrichstring.cpp
new file mode 100644
index 0000000..0bf3f12
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxrichstring.cpp
@@ -0,0 +1,329 @@
+// xlsxrichstring.cpp
+
+#include <QtGlobal>
+#include <QDebug>
+#include <QTextDocument>
+#include <QTextFragment>
+
+#include "xlsxrichstring.h"
+#include "xlsxrichstring_p.h"
+#include "xlsxformat_p.h"
+
+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)
+{
+    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.size() == 0;
+}
+
+/*!
+    Returns true is this is an empty string.
+ */
+bool RichString::isEmtpy() const
+{
+    for (const auto& str : d->fragmentTexts) {
+        if (!str.isEmpty())
+            return false;
+    }
+
+    return true;
+}
+
+/*!
+    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) {
+        RichStringPrivate *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
diff --git a/internal_system_v1/QXlsx/source/xlsxsharedstrings.cpp b/internal_system_v1/QXlsx/source/xlsxsharedstrings.cpp
new file mode 100644
index 0000000..dbb4a2a
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxsharedstrings.cpp
@@ -0,0 +1,382 @@
+// xlsxsharedstrings.cpp
+
+#include <QtGlobal>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QDir>
+#include <QFile>
+#include <QDebug>
+#include <QBuffer>
+
+#include "xlsxrichstring.h"
+#include "xlsxsharedstrings_p.h"
+#include "xlsxutility_p.h"
+#include "xlsxformat_p.h"
+#include "xlsxcolor_p.h"
+
+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: invlid 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)) {
+        XlsxColor 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();
+                 if ((hasUniqueCountAttr = attributes.hasAttribute(QLatin1String("uniqueCount"))))
+                     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
diff --git a/internal_system_v1/QXlsx/source/xlsxsimpleooxmlfile.cpp b/internal_system_v1/QXlsx/source/xlsxsimpleooxmlfile.cpp
new file mode 100644
index 0000000..380ce6b
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxsimpleooxmlfile.cpp
@@ -0,0 +1,37 @@
+// xlsxsimpleooxmlfile.cpp
+
+#include "xlsxsimpleooxmlfile_p.h"
+
+#include <QtGlobal>
+#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
diff --git a/internal_system_v1/QXlsx/source/xlsxstyles.cpp b/internal_system_v1/QXlsx/source/xlsxstyles.cpp
new file mode 100644
index 0000000..9be9a60
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxstyles.cpp
@@ -0,0 +1,1409 @@
+// xlsxstyles.cpp
+
+#include <QtGlobal>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QFile>
+#include <QMap>
+#include <QDataStream>
+#include <QDebug>
+#include <QBuffer>
+
+#include "xlsxglobal.h"
+#include "xlsxstyles_p.h"
+#include "xlsxformat_p.h"
+#include "xlsxutility_p.h"
+#include "xlsxcolor_p.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+/*
+  When loading from existing .xlsx file. we should create a clean styles object.
+  otherwise, default formats should be added.
+
+*/
+Styles::Styles(CreateFlag flag)
+    : AbstractOOXmlFile(flag), m_nextCustomNumFmtId(176), m_isIndexedColorsDefault(true)
+    , m_emptyFormatAdded(false)
+{
+    //!Fix me. Should the custom num fmt Id starts with 164 or 176 or others??
+
+    //!Fix me! Where should we put these register code?
+
+    // issue #172, #89
+#if QT_VERSION >= 0x060000 // Qt 6.0 or over
+    if (QMetaType::fromName("XlsxColor").isRegistered())
+#else
+    if (QMetaType::type("XlsxColor") == QMetaType::UnknownType)
+#endif
+    {
+        qRegisterMetaType<XlsxColor>("XlsxColor");
+
+#if QT_VERSION >= 0x060000
+        // Qt 6
+
+        ///TODO:
+
+#else
+        // Qt 5
+
+        qRegisterMetaTypeStreamOperators<XlsxColor>("XlsxColor");
+
+        QMetaType::registerDebugStreamOperator<XlsxColor>();
+
+#endif
+    }
+
+    if (flag == F_NewFromScratch) {
+        //Add default Format
+        Format defaultFmt;
+        addXfFormat(defaultFmt);
+
+        //Add another fill format
+        Format fillFmt;
+        fillFmt.setFillPattern(Format::PatternGray125);
+        m_fillsList.append(fillFmt);
+        m_fillsHash.insert(fillFmt.fillKey(), fillFmt);
+    }
+}
+
+Styles::~Styles()
+{
+}
+
+Format Styles::xfFormat(int idx) const
+{
+    if (idx <0 || idx >= m_xf_formatsList.size())
+        return Format();
+
+    return m_xf_formatsList[idx];
+}
+
+Format Styles::dxfFormat(int idx) const
+{
+    if (idx <0 || idx >= m_dxf_formatsList.size())
+        return Format();
+
+    return m_dxf_formatsList[idx];
+}
+
+// dev74 issue#57
+void Styles::fixNumFmt(const Format &format)
+{
+    if (!format.hasNumFmtData())
+        return;
+
+    if (format.hasProperty(FormatPrivate::P_NumFmt_Id)
+            && !format.stringProperty(FormatPrivate::P_NumFmt_FormatCode).isEmpty())
+    {
+        return;
+    }
+
+    if ( m_builtinNumFmtsHash.isEmpty() )
+    {
+        m_builtinNumFmtsHash.insert(QStringLiteral("General"), 0);
+        m_builtinNumFmtsHash.insert(QStringLiteral("0"), 1);
+        m_builtinNumFmtsHash.insert(QStringLiteral("0.00"), 2);
+        m_builtinNumFmtsHash.insert(QStringLiteral("#,##0"), 3);
+        m_builtinNumFmtsHash.insert(QStringLiteral("#,##0.00"), 4);
+//            m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0_);($#,##0)"), 5);
+//            m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0_);[Red]($#,##0)"), 6);
+//            m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0.00_);($#,##0.00)"), 7);
+//            m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0.00_);[Red]($#,##0.00)"), 8);
+        m_builtinNumFmtsHash.insert(QStringLiteral("0%"), 9);
+        m_builtinNumFmtsHash.insert(QStringLiteral("0.00%"), 10);
+        m_builtinNumFmtsHash.insert(QStringLiteral("0.00E+00"), 11);
+        m_builtinNumFmtsHash.insert(QStringLiteral("# ?/?"), 12);
+        m_builtinNumFmtsHash.insert(QStringLiteral("# ?\?/??"), 13);// Note: "??/" is a c++ trigraph, so escape one "?"
+        m_builtinNumFmtsHash.insert(QStringLiteral("m/d/yy"), 14);
+        m_builtinNumFmtsHash.insert(QStringLiteral("d-mmm-yy"), 15);
+        m_builtinNumFmtsHash.insert(QStringLiteral("d-mmm"), 16);
+        m_builtinNumFmtsHash.insert(QStringLiteral("mmm-yy"), 17);
+        m_builtinNumFmtsHash.insert(QStringLiteral("h:mm AM/PM"), 18);
+        m_builtinNumFmtsHash.insert(QStringLiteral("h:mm:ss AM/PM"), 19);
+        m_builtinNumFmtsHash.insert(QStringLiteral("h:mm"), 20);
+        m_builtinNumFmtsHash.insert(QStringLiteral("h:mm:ss"), 21);
+        m_builtinNumFmtsHash.insert(QStringLiteral("m/d/yy h:mm"), 22);
+
+        m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0_);(#,##0)"), 37);
+        m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0_);[Red](#,##0)"), 38);
+        m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0.00_);(#,##0.00)"), 39);
+        m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0.00_);[Red](#,##0.00)"), 40);
+//            m_builtinNumFmtsHash.insert(QStringLiteral("_(* #,##0_);_(* (#,##0);_(* \"-\"_);_(_)"), 41);
+//            m_builtinNumFmtsHash.insert(QStringLiteral("_($* #,##0_);_($* (#,##0);_($* \"-\"_);_(_)"), 42);
+//            m_builtinNumFmtsHash.insert(QStringLiteral("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(_)"), 43);
+//            m_builtinNumFmtsHash.insert(QStringLiteral("_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(_)"), 44);
+        m_builtinNumFmtsHash.insert(QStringLiteral("mm:ss"), 45);
+        m_builtinNumFmtsHash.insert(QStringLiteral("[h]:mm:ss"), 46);
+        m_builtinNumFmtsHash.insert(QStringLiteral("mm:ss.0"), 47);
+        m_builtinNumFmtsHash.insert(QStringLiteral("##0.0E+0"), 48);
+        m_builtinNumFmtsHash.insert(QStringLiteral("@"), 49);
+
+        // dev74
+        // m_builtinNumFmtsHash.insert(QStringLiteral("0.####"), 176);
+
+    }
+
+    const auto& str = format.numberFormat();
+    if (!str.isEmpty())
+    {
+        QHash<QString, QSharedPointer<XlsxFormatNumberData> >::ConstIterator cIt;
+        //Assign proper number format index
+        const auto& it = m_builtinNumFmtsHash.constFind(str);
+        if (it != m_builtinNumFmtsHash.constEnd())
+        {
+            const_cast<Format *>(&format)->fixNumberFormat(it.value(), str);
+        }
+        else if ((cIt = m_customNumFmtsHash.constFind(str)) != m_customNumFmtsHash.constEnd())
+        {
+            const_cast<Format *>(&format)->fixNumberFormat(cIt.value()->formatIndex, str);
+        }
+        else
+        {
+            //Assign a new fmt Id.
+            const_cast<Format *>(&format)->fixNumberFormat(m_nextCustomNumFmtId, str);
+
+            QSharedPointer<XlsxFormatNumberData> fmt(new XlsxFormatNumberData);
+            fmt->formatIndex = m_nextCustomNumFmtId;
+            fmt->formatString = str;
+            m_customNumFmtIdMap.insert(m_nextCustomNumFmtId, fmt);
+            m_customNumFmtsHash.insert(str, fmt);
+
+            m_nextCustomNumFmtId += 1;
+        }
+    }
+    else
+    {
+        const auto id = format.numberFormatIndex();
+        //Assign proper format code, this is needed by dxf format
+        const auto& it = m_customNumFmtIdMap.constFind(id);
+        if (it != m_customNumFmtIdMap.constEnd())
+        {
+            const_cast<Format *>(&format)->fixNumberFormat(id, it.value()->formatString);
+        }
+        else
+        {
+            bool found = false;
+            for ( auto&& it = m_builtinNumFmtsHash.constBegin() ; it != m_builtinNumFmtsHash.constEnd() ; ++it )
+            {
+                if (it.value() == id)
+                {
+                    const_cast<Format *>(&format)->fixNumberFormat(id, it.key());
+                    found = true;
+                    break;
+                }
+            }
+
+            if (!found)
+            {
+                //Wrong numFmt
+                const_cast<Format *>(&format)->fixNumberFormat(id, QStringLiteral("General"));
+            }
+        }
+    }
+}
+
+/*
+   Assign index to Font/Fill/Border and Format
+
+   When \a force is true, add the format to the format list, even other format has
+   the same key have been in.
+   This is useful when reading existing .xlsx files which may contains duplicated formats.
+*/
+void Styles::addXfFormat(const Format &format, bool force)
+{
+    if (format.isEmpty())
+    {
+        //Try do something for empty Format.
+        if (m_emptyFormatAdded && !force)
+            return;
+
+        m_emptyFormatAdded = true;
+    }
+
+    //numFmt
+    if (format.hasNumFmtData() &&
+            !format.hasProperty(FormatPrivate::P_NumFmt_Id))
+    {
+        fixNumFmt(format);
+    }
+
+    //Font
+    const auto& fontIt = m_fontsHash.constFind(format.fontKey());
+    if (format.hasFontData() && !format.fontIndexValid())
+    {
+        //Assign proper font index, if has font data.
+        if (fontIt == m_fontsHash.constEnd())
+            const_cast<Format *>(&format)->setFontIndex(m_fontsList.size());
+        else
+            const_cast<Format *>(&format)->setFontIndex(fontIt->fontIndex());
+    }
+    if (fontIt == m_fontsHash.constEnd())
+    {
+        //Still a valid font if the format has no fontData. (All font properties are default)
+        m_fontsList.append(format);
+        m_fontsHash[format.fontKey()] = format;
+    }
+
+    //Fill
+    const auto& fillIt = m_fillsHash.constFind(format.fillKey());
+    if (format.hasFillData() && !format.fillIndexValid()) {
+        //Assign proper fill index, if has fill data.
+        if (fillIt == m_fillsHash.constEnd())
+            const_cast<Format *>(&format)->setFillIndex(m_fillsList.size());
+        else
+            const_cast<Format *>(&format)->setFillIndex(fillIt->fillIndex());
+    }
+    if (fillIt == m_fillsHash.constEnd()) {
+        //Still a valid fill if the format has no fillData. (All fill properties are default)
+        m_fillsList.append(format);
+        m_fillsHash[format.fillKey()] = format;
+    }
+
+    //Border
+    const auto& borderIt = m_bordersHash.constFind(format.borderKey());
+    if (format.hasBorderData() && !format.borderIndexValid()) {
+        //Assign proper border index, if has border data.
+        if (borderIt == m_bordersHash.constEnd())
+            const_cast<Format *>(&format)->setBorderIndex(m_bordersList.size());
+        else
+            const_cast<Format *>(&format)->setBorderIndex(borderIt->borderIndex());
+    }
+    if (borderIt == m_bordersHash.constEnd()) {
+        //Still a valid border if the format has no borderData. (All border properties are default)
+        m_bordersList.append(format);
+        m_bordersHash[format.borderKey()] = format;
+    }
+
+    //Format
+    const auto& formatIt = m_xf_formatsHash.constFind(format.formatKey());
+    if (!format.isEmpty() && !format.xfIndexValid())
+    {
+        if (formatIt == m_xf_formatsHash.constEnd())
+            const_cast<Format *>(&format)->setXfIndex(m_xf_formatsList.size());
+        else
+            const_cast<Format *>(&format)->setXfIndex(formatIt->xfIndex());
+    }
+
+    if (formatIt == m_xf_formatsHash.constEnd() ||
+            force)
+    {
+        m_xf_formatsList.append(format);
+        m_xf_formatsHash[format.formatKey()] = format;
+    }
+}
+
+void Styles::addDxfFormat(const Format &format, bool force)
+{
+    //numFmt
+    if ( format.hasNumFmtData() )
+    {
+        fixNumFmt(format);
+    }
+
+    const auto& formatIt = m_dxf_formatsHash.constFind(format.formatKey());
+    if ( !format.isEmpty() &&
+            !format.dxfIndexValid() )
+    {
+        if (formatIt ==  m_dxf_formatsHash.constEnd() ) // m_xf_formatsHash.constEnd()) // issue #108
+        {
+            const_cast<Format *>(&format)->setDxfIndex( m_dxf_formatsList.size() );
+        }
+        else
+        {
+            const_cast<Format *>(&format)->setDxfIndex( formatIt->dxfIndex() );
+        }
+    }
+
+    if (formatIt == m_xf_formatsHash.constEnd() ||
+         force )
+    {
+        m_dxf_formatsList.append(format);
+        m_dxf_formatsHash[ format.formatKey() ] = format;
+    }
+}
+
+void Styles::saveToXmlFile(QIODevice *device) const
+{
+    QXmlStreamWriter writer(device);
+
+    writer.writeStartDocument(QStringLiteral("1.0"), true);
+    writer.writeStartElement(QStringLiteral("styleSheet"));
+    writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main"));
+
+    writeNumFmts(writer);
+    writeFonts(writer);
+    writeFills(writer);
+    writeBorders(writer);
+
+    writer.writeStartElement(QStringLiteral("cellStyleXfs"));
+    writer.writeAttribute(QStringLiteral("count"), QStringLiteral("1"));
+    writer.writeStartElement(QStringLiteral("xf"));
+    writer.writeAttribute(QStringLiteral("numFmtId"), QStringLiteral("0"));
+    writer.writeAttribute(QStringLiteral("fontId"), QStringLiteral("0"));
+    writer.writeAttribute(QStringLiteral("fillId"), QStringLiteral("0"));
+    writer.writeAttribute(QStringLiteral("borderId"), QStringLiteral("0"));
+    writer.writeEndElement();//xf
+    writer.writeEndElement();//cellStyleXfs
+
+    writeCellXfs(writer);
+
+    writer.writeStartElement(QStringLiteral("cellStyles"));
+    writer.writeAttribute(QStringLiteral("count"), QStringLiteral("1"));
+    writer.writeStartElement(QStringLiteral("cellStyle"));
+    writer.writeAttribute(QStringLiteral("name"), QStringLiteral("Normal"));
+    writer.writeAttribute(QStringLiteral("xfId"), QStringLiteral("0"));
+    writer.writeAttribute(QStringLiteral("builtinId"), QStringLiteral("0"));
+    writer.writeEndElement();//cellStyle
+    writer.writeEndElement();//cellStyles
+
+    writeDxfs(writer);
+
+    writer.writeStartElement(QStringLiteral("tableStyles"));
+    writer.writeAttribute(QStringLiteral("count"), QStringLiteral("0"));
+    writer.writeAttribute(QStringLiteral("defaultTableStyle"), QStringLiteral("TableStyleMedium9"));
+    writer.writeAttribute(QStringLiteral("defaultPivotStyle"), QStringLiteral("PivotStyleLight16"));
+    writer.writeEndElement();//tableStyles
+
+    writeColors(writer);
+
+    writer.writeEndElement();//styleSheet
+    writer.writeEndDocument();
+}
+
+void Styles::writeNumFmts(QXmlStreamWriter &writer) const
+{
+    if (m_customNumFmtIdMap.size() == 0)
+        return;
+
+    writer.writeStartElement(QStringLiteral("numFmts"));
+    writer.writeAttribute(QStringLiteral("count"), QString::number(m_customNumFmtIdMap.count()));
+
+    QMapIterator<int, QSharedPointer<XlsxFormatNumberData> > it(m_customNumFmtIdMap);
+    while (it.hasNext()) {
+        it.next();
+        writer.writeEmptyElement(QStringLiteral("numFmt"));
+        writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(it.value()->formatIndex));
+        writer.writeAttribute(QStringLiteral("formatCode"), it.value()->formatString);
+    }
+    writer.writeEndElement();//numFmts
+}
+
+/*
+*/
+void Styles::writeFonts(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("fonts"));
+    writer.writeAttribute(QStringLiteral("count"), QString::number(m_fontsList.count()));
+    for (const auto &font : m_fontsList) {
+        writeFont(writer, font, false);
+    }
+    writer.writeEndElement();//fonts
+}
+
+void Styles::writeFont(QXmlStreamWriter &writer, const Format &format, bool isDxf) const
+{
+    writer.writeStartElement(QStringLiteral("font"));
+
+    //The condense and extend elements are mainly used in dxf format
+    if (format.hasProperty(FormatPrivate::P_Font_Condense)
+            && !format.boolProperty(FormatPrivate::P_Font_Condense)) {
+        writer.writeEmptyElement(QStringLiteral("condense"));
+        writer.writeAttribute(QStringLiteral("val"), QStringLiteral("0"));
+    }
+    if (format.hasProperty(FormatPrivate::P_Font_Extend)
+            && !format.boolProperty(FormatPrivate::P_Font_Extend)) {
+        writer.writeEmptyElement(QStringLiteral("extend"));
+        writer.writeAttribute(QStringLiteral("val"), QStringLiteral("0"));
+    }
+
+    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 (!isDxf && 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)) {
+        XlsxColor color = format.property(FormatPrivate::P_Font_Color).value<XlsxColor>();
+        color.saveToXml(writer);
+    }
+
+    if (!isDxf) {
+        if (!format.fontName().isEmpty()) {
+            writer.writeEmptyElement(QStringLiteral("name"));
+            writer.writeAttribute(QStringLiteral("val"), format.fontName());
+        }
+        if (format.hasProperty(FormatPrivate::P_Font_Charset)) {
+            writer.writeEmptyElement(QStringLiteral("charset"));
+            writer.writeAttribute(QStringLiteral("val"), QString::number(format.intProperty(FormatPrivate::P_Font_Charset)));
+        }
+        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));
+        }
+    }
+    writer.writeEndElement(); //font
+}
+
+void Styles::writeFills(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("fills"));
+    writer.writeAttribute(QStringLiteral("count"), QString::number(m_fillsList.size()));
+
+    for (const auto &fill : m_fillsList) {
+        writeFill(writer, fill);
+    }
+
+    writer.writeEndElement(); //fills
+}
+
+void Styles::writeFill(QXmlStreamWriter &writer, const Format &fill, bool isDxf) const
+{
+    static const QMap<int, QString> patternStrings = {
+        {Format::PatternNone, QStringLiteral("none")},
+        {Format::PatternSolid, QStringLiteral("solid")},
+        {Format::PatternMediumGray, QStringLiteral("mediumGray")},
+        {Format::PatternDarkGray, QStringLiteral("darkGray")},
+        {Format::PatternLightGray, QStringLiteral("lightGray")},
+        {Format::PatternDarkHorizontal, QStringLiteral("darkHorizontal")},
+        {Format::PatternDarkVertical, QStringLiteral("darkVertical")},
+        {Format::PatternDarkDown, QStringLiteral("darkDown")},
+        {Format::PatternDarkUp, QStringLiteral("darkUp")},
+        {Format::PatternDarkGrid, QStringLiteral("darkGrid")},
+        {Format::PatternDarkTrellis, QStringLiteral("darkTrellis")},
+        {Format::PatternLightHorizontal, QStringLiteral("lightHorizontal")},
+        {Format::PatternLightVertical, QStringLiteral("lightVertical")},
+        {Format::PatternLightDown, QStringLiteral("lightDown")},
+        {Format::PatternLightUp, QStringLiteral("lightUp")},
+        {Format::PatternLightTrellis, QStringLiteral("lightTrellis")},
+        {Format::PatternGray125, QStringLiteral("gray125")},
+        {Format::PatternGray0625, QStringLiteral("gray0625")},
+        {Format::PatternLightGrid, QStringLiteral("lightGrid")}
+    };
+
+    writer.writeStartElement(QStringLiteral("fill"));
+    writer.writeStartElement(QStringLiteral("patternFill"));
+    Format::FillPattern pattern = fill.fillPattern();
+    // For normal fill formats, Excel prefer to outputing the default "none" attribute
+    // But for dxf, Excel prefer to omiting the default "none"
+    // Though not make any difference, but it make easier to compare origin files with generate files during debug
+    if (!(pattern == Format::PatternNone && isDxf))
+        writer.writeAttribute(QStringLiteral("patternType"), patternStrings[pattern]);
+    // For a solid fill, Excel reverses the role of foreground and background colours
+    if (fill.fillPattern() == Format::PatternSolid) {
+        if (fill.hasProperty(FormatPrivate::P_Fill_BgColor))
+            fill.property(FormatPrivate::P_Fill_BgColor).value<XlsxColor>().saveToXml(writer, QStringLiteral("fgColor"));
+        if (fill.hasProperty(FormatPrivate::P_Fill_FgColor))
+            fill.property(FormatPrivate::P_Fill_FgColor).value<XlsxColor>().saveToXml(writer, QStringLiteral("bgColor"));
+    } else {
+        if (fill.hasProperty(FormatPrivate::P_Fill_FgColor))
+            fill.property(FormatPrivate::P_Fill_FgColor).value<XlsxColor>().saveToXml(writer, QStringLiteral("fgColor"));
+        if (fill.hasProperty(FormatPrivate::P_Fill_BgColor))
+            fill.property(FormatPrivate::P_Fill_BgColor).value<XlsxColor>().saveToXml(writer, QStringLiteral("bgColor"));
+    }
+    writer.writeEndElement();//patternFill
+    writer.writeEndElement();//fill
+}
+
+void Styles::writeBorders(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("borders"));
+    writer.writeAttribute(QStringLiteral("count"), QString::number(m_bordersList.count()));
+
+    for (const auto &border : m_bordersList) {
+        writeBorder(writer, border);
+    }
+
+    writer.writeEndElement();//borders
+}
+
+void Styles::writeBorder(QXmlStreamWriter &writer, const Format &border, bool isDxf) const
+{
+    writer.writeStartElement(QStringLiteral("border"));
+    if (border.hasProperty(FormatPrivate::P_Border_DiagonalType)) {
+        Format::DiagonalBorderType t = border.diagonalBorderType();
+        if (t == Format::DiagonalBorderUp) {
+            writer.writeAttribute(QStringLiteral("diagonalUp"), QStringLiteral("1"));
+        } else if (t == Format::DiagonalBorderDown) {
+            writer.writeAttribute(QStringLiteral("diagonalDown"), QStringLiteral("1"));
+        } else if (t == Format::DiagnoalBorderBoth) {
+            writer.writeAttribute(QStringLiteral("diagonalUp"), QStringLiteral("1"));
+            writer.writeAttribute(QStringLiteral("diagonalDown"), QStringLiteral("1"));
+        }
+    }
+
+    writeSubBorder(writer, QStringLiteral("left"), border.leftBorderStyle(), border.property(FormatPrivate::P_Border_LeftColor).value<XlsxColor>());
+    writeSubBorder(writer, QStringLiteral("right"), border.rightBorderStyle(), border.property(FormatPrivate::P_Border_RightColor).value<XlsxColor>());
+    writeSubBorder(writer, QStringLiteral("top"), border.topBorderStyle(), border.property(FormatPrivate::P_Border_TopColor).value<XlsxColor>());
+    writeSubBorder(writer, QStringLiteral("bottom"), border.bottomBorderStyle(), border.property(FormatPrivate::P_Border_BottomColor).value<XlsxColor>());
+
+    //Condition DXF formats don't allow diagonal style
+    if (!isDxf)
+        writeSubBorder(writer, QStringLiteral("diagonal"), border.diagonalBorderStyle(), border.property(FormatPrivate::P_Border_DiagonalColor).value<XlsxColor>());
+
+    if (isDxf) {
+//        writeSubBorder(wirter, QStringLiteral("vertical"), );
+//        writeSubBorder(writer, QStringLiteral("horizontal"), );
+    }
+
+    writer.writeEndElement();//border
+}
+
+void Styles::writeSubBorder(QXmlStreamWriter &writer, const QString &type, int style, const XlsxColor &color) const
+{
+    if (style == Format::BorderNone) {
+        writer.writeEmptyElement(type);
+        return;
+    }
+
+    static const QMap<int, QString> stylesString = {
+        {Format::BorderNone, QStringLiteral("none")},
+        {Format::BorderThin, QStringLiteral("thin")},
+        {Format::BorderMedium, QStringLiteral("medium")},
+        {Format::BorderDashed, QStringLiteral("dashed")},
+        {Format::BorderDotted, QStringLiteral("dotted")},
+        {Format::BorderThick, QStringLiteral("thick")},
+        {Format::BorderDouble, QStringLiteral("double")},
+        {Format::BorderHair, QStringLiteral("hair")},
+        {Format::BorderMediumDashed, QStringLiteral("mediumDashed")},
+        {Format::BorderDashDot, QStringLiteral("dashDot")},
+        {Format::BorderMediumDashDot, QStringLiteral("mediumDashDot")},
+        {Format::BorderDashDotDot, QStringLiteral("dashDotDot")},
+        {Format::BorderMediumDashDotDot, QStringLiteral("mediumDashDotDot")},
+        {Format::BorderSlantDashDot, QStringLiteral("slantDashDot")}
+    };
+
+    writer.writeStartElement(type);
+    writer.writeAttribute(QStringLiteral("style"), stylesString[style]);
+    color.saveToXml(writer); //write color element
+
+    writer.writeEndElement();//type
+}
+
+void Styles::writeCellXfs(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("cellXfs"));
+    writer.writeAttribute(QStringLiteral("count"), QString::number(m_xf_formatsList.size()));
+    for (const Format &format : m_xf_formatsList) {
+        int xf_id = 0;
+        writer.writeStartElement(QStringLiteral("xf"));
+        writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(format.numberFormatIndex()));
+        writer.writeAttribute(QStringLiteral("fontId"), QString::number(format.fontIndex()));
+        writer.writeAttribute(QStringLiteral("fillId"), QString::number(format.fillIndex()));
+        writer.writeAttribute(QStringLiteral("borderId"), QString::number(format.borderIndex()));
+        writer.writeAttribute(QStringLiteral("xfId"), QString::number(xf_id));
+        if (format.hasNumFmtData())
+            writer.writeAttribute(QStringLiteral("applyNumberFormat"), QStringLiteral("1"));
+        if (format.hasFontData())
+            writer.writeAttribute(QStringLiteral("applyFont"), QStringLiteral("1"));
+        if (format.hasFillData())
+            writer.writeAttribute(QStringLiteral("applyFill"), QStringLiteral("1"));
+        if (format.hasBorderData())
+            writer.writeAttribute(QStringLiteral("applyBorder"), QStringLiteral("1"));
+        if (format.hasAlignmentData())
+            writer.writeAttribute(QStringLiteral("applyAlignment"), QStringLiteral("1"));
+
+        if (format.hasAlignmentData()) {
+            writer.writeEmptyElement(QStringLiteral("alignment"));
+            if (format.hasProperty(FormatPrivate::P_Alignment_AlignH)) {
+                switch (format.horizontalAlignment()) {
+                case Format::AlignLeft:
+                    writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("left"));
+                    break;
+                case Format::AlignHCenter:
+                    writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("center"));
+                    break;
+                case Format::AlignRight:
+                    writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("right"));
+                    break;
+                case Format::AlignHFill:
+                    writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("fill"));
+                    break;
+                case Format::AlignHJustify:
+                    writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("justify"));
+                    break;
+                case Format::AlignHMerge:
+                    writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("centerContinuous"));
+                    break;
+                case Format::AlignHDistributed:
+                    writer.writeAttribute(QStringLiteral("horizontal"), QStringLiteral("distributed"));
+                    break;
+                default:
+                    break;
+                }
+            }
+
+            if (format.hasProperty(FormatPrivate::P_Alignment_AlignV)) {
+                switch (format.verticalAlignment()) {
+                case Format::AlignTop:
+                    writer.writeAttribute(QStringLiteral("vertical"), QStringLiteral("top"));
+                    break;
+                case Format::AlignVCenter:
+                    writer.writeAttribute(QStringLiteral("vertical"), QStringLiteral("center"));
+                    break;
+                case Format::AlignVJustify:
+                    writer.writeAttribute(QStringLiteral("vertical"), QStringLiteral("justify"));
+                    break;
+                case Format::AlignVDistributed:
+                    writer.writeAttribute(QStringLiteral("vertical"), QStringLiteral("distributed"));
+                    break;
+                default:
+                    break;
+                }
+            }
+            if (format.hasProperty(FormatPrivate::P_Alignment_Indent))
+                writer.writeAttribute(QStringLiteral("indent"), QString::number(format.indent()));
+            if (format.hasProperty(FormatPrivate::P_Alignment_Wrap) && format.textWrap())
+                writer.writeAttribute(QStringLiteral("wrapText"), QStringLiteral("1"));
+            if (format.hasProperty(FormatPrivate::P_Alignment_ShinkToFit) && format.shrinkToFit())
+                writer.writeAttribute(QStringLiteral("shrinkToFit"), QStringLiteral("1"));
+            if (format.hasProperty(FormatPrivate::P_Alignment_Rotation))
+                writer.writeAttribute(QStringLiteral("textRotation"), QString::number(format.rotation()));
+        }
+
+        writer.writeEndElement();//xf
+    }
+    writer.writeEndElement();//cellXfs
+}
+
+void Styles::writeDxfs(QXmlStreamWriter &writer) const
+{
+    writer.writeStartElement(QStringLiteral("dxfs"));
+    writer.writeAttribute(QStringLiteral("count"), QString::number(m_dxf_formatsList.size()));
+    for (const Format &format : m_dxf_formatsList)
+        writeDxf(writer, format);
+    writer.writeEndElement(); //dxfs
+}
+
+void Styles::writeDxf(QXmlStreamWriter &writer, const Format &format) const
+{
+    writer.writeStartElement(QStringLiteral("dxf"));
+
+    if (format.hasFontData())
+        writeFont(writer, format, true);
+
+    if (format.hasNumFmtData()) {
+        writer.writeEmptyElement(QStringLiteral("numFmt"));
+        writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(format.numberFormatIndex()));
+        writer.writeAttribute(QStringLiteral("formatCode"), format.numberFormat());
+    }
+
+    if (format.hasFillData())
+        writeFill(writer, format, true);
+
+    if (format.hasBorderData())
+        writeBorder(writer, format, true);
+
+    writer.writeEndElement();//dxf
+}
+
+void Styles::writeColors(QXmlStreamWriter &writer) const
+{
+    if (m_isIndexedColorsDefault) //Don't output the default indexdeColors
+        return;
+
+    writer.writeStartElement(QStringLiteral("colors"));
+
+    writer.writeStartElement(QStringLiteral("indexedColors"));
+    for (const QColor &color : m_indexedColors) {
+        writer.writeEmptyElement(QStringLiteral("rgbColor"));
+        writer.writeAttribute(QStringLiteral("rgb"), XlsxColor::toARGBString(color));
+    }
+
+    writer.writeEndElement();//indexedColors
+
+    writer.writeEndElement();//colors
+}
+
+bool Styles::readNumFmts(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("numFmts"));
+    const auto& attributes = reader.attributes();
+    const auto hasCount = attributes.hasAttribute(QLatin1String("count"));
+    const auto count = hasCount ? attributes.value(QLatin1String("count")).toInt() : -1;
+
+    //Read utill we find the numFmts end tag or ....
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+           && reader.name() == QLatin1String("numFmts"))) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("numFmt")) {
+                const auto& attributes = reader.attributes();
+                QSharedPointer<XlsxFormatNumberData> fmt (new XlsxFormatNumberData);
+                fmt->formatIndex = attributes.value(QLatin1String("numFmtId")).toInt();
+                fmt->formatString = attributes.value(QLatin1String("formatCode")).toString();
+                if (fmt->formatIndex >= m_nextCustomNumFmtId)
+                    m_nextCustomNumFmtId = fmt->formatIndex + 1;
+                m_customNumFmtIdMap.insert(fmt->formatIndex, fmt);
+                m_customNumFmtsHash.insert(fmt->formatString, fmt);
+            }
+        }
+    }
+
+    if (reader.hasError())
+        qWarning()<<reader.errorString();
+
+    if (hasCount && (count != m_customNumFmtIdMap.size()))
+        qWarning("error read custom numFmts");
+
+    return true;
+}
+
+bool Styles::readFonts(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("fonts"));
+    const auto& attributes = reader.attributes();
+    const auto hasCount = attributes.hasAttribute(QLatin1String("count"));
+    const auto count = hasCount ? attributes.value(QLatin1String("count")).toInt() : -1;
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                               && reader.name() == QLatin1String("fonts"))) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("font")) {
+                Format format;
+                readFont(reader, format);
+                m_fontsList.append(format);
+                m_fontsHash.insert(format.fontKey(), format);
+                if (format.isValid())
+                    format.setFontIndex(m_fontsList.size()-1);
+            }
+        }
+    }
+    if (reader.hasError())
+        qWarning()<<reader.errorString();
+
+    if (hasCount && (count != m_fontsList.size()))
+        qWarning("error read fonts");
+    return true;
+}
+
+bool Styles::readFont(QXmlStreamReader &reader, Format &format)
+{
+    Q_ASSERT(reader.name() == QLatin1String("font"));
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                               && reader.name() == QLatin1String("font"))) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            const auto& attributes = reader.attributes();
+            if (reader.name() == QLatin1String("name")) {
+                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")) {
+                const auto sz = attributes.value(QLatin1String("val")).toInt();
+                format.setFontSize(sz);
+            } 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 true;
+}
+
+bool Styles::readFills(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("fills"));
+
+    const auto& attributes = reader.attributes();
+    const auto hasCount = attributes.hasAttribute(QLatin1String("count"));
+    const auto count = hasCount ? attributes.value(QLatin1String("count")).toInt() : -1;
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                               && reader.name() == QLatin1String("fills"))) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("fill")) {
+                Format fill;
+                readFill(reader, fill);
+                m_fillsList.append(fill);
+                m_fillsHash.insert(fill.fillKey(), fill);
+                if (fill.isValid())
+                    fill.setFillIndex(m_fillsList.size()-1);
+            }
+        }
+    }
+    if (reader.hasError())
+        qWarning()<<reader.errorString();
+
+    if (hasCount && (count != m_fillsList.size()))
+        qWarning("error read fills");
+    return true;
+}
+
+bool Styles::readFill(QXmlStreamReader &reader, Format &fill)
+{
+    Q_ASSERT(reader.name() == QLatin1String("fill"));
+
+    static const QMap<QString, Format::FillPattern> patternValues = {
+        {QStringLiteral("none"), Format::PatternNone},
+        {QStringLiteral("solid"), Format::PatternSolid},
+        {QStringLiteral("mediumGray"), Format::PatternMediumGray},
+        {QStringLiteral("darkGray"), Format::PatternDarkGray},
+        {QStringLiteral("lightGray"), Format::PatternLightGray},
+        {QStringLiteral("darkHorizontal"), Format::PatternDarkHorizontal},
+        {QStringLiteral("darkVertical"), Format::PatternDarkVertical},
+        {QStringLiteral("darkDown"), Format::PatternDarkDown},
+        {QStringLiteral("darkUp"), Format::PatternDarkUp},
+        {QStringLiteral("darkGrid"), Format::PatternDarkGrid},
+        {QStringLiteral("darkTrellis"), Format::PatternDarkTrellis},
+        {QStringLiteral("lightHorizontal"), Format::PatternLightHorizontal},
+        {QStringLiteral("lightVertical"), Format::PatternLightVertical},
+        {QStringLiteral("lightDown"), Format::PatternLightDown},
+        {QStringLiteral("lightUp"), Format::PatternLightUp},
+        {QStringLiteral("lightTrellis"), Format::PatternLightTrellis},
+        {QStringLiteral("gray125"), Format::PatternGray125},
+        {QStringLiteral("gray0625"), Format::PatternGray0625},
+        {QStringLiteral("lightGrid"), Format::PatternLightGrid}
+    };
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("fill"))) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("patternFill")) {
+                const auto& attributes = reader.attributes();
+                if (attributes.hasAttribute(QLatin1String("patternType"))) {
+                    const auto& it = patternValues.constFind(attributes.value(QLatin1String("patternType")).toString());
+                    fill.setFillPattern(it != patternValues.constEnd() ? it.value() : Format::PatternNone);
+
+                    //parse foreground and background colors if they exist
+                    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("patternFill"))) {
+                        reader.readNextStartElement();
+                        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+                            if (reader.name() == QLatin1String("fgColor")) {
+                                XlsxColor c;
+                                if ( c.loadFromXml(reader) )
+                                {
+                                    if (fill.fillPattern() == Format::PatternSolid)
+                                        fill.setProperty(FormatPrivate::P_Fill_BgColor, c);
+                                    else
+                                        fill.setProperty(FormatPrivate::P_Fill_FgColor, c);
+                                }
+                            } else if (reader.name() == QLatin1String("bgColor")) {
+                                XlsxColor c;
+                                if ( c.loadFromXml(reader) )
+                                {
+                                    if (fill.fillPattern() == Format::PatternSolid)
+                                        fill.setProperty(FormatPrivate::P_Fill_FgColor, c);
+                                    else
+                                        fill.setProperty(FormatPrivate::P_Fill_BgColor, c);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+bool Styles::readBorders(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("borders"));
+
+    const auto& attributes = reader.attributes();
+    const auto hasCount = attributes.hasAttribute(QLatin1String("count"));
+    const auto count = hasCount ? attributes.value(QLatin1String("count")).toInt() : -1;
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                               && reader.name() == QLatin1String("borders"))) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("border")) {
+                Format border;
+                readBorder(reader, border);
+                m_bordersList.append(border);
+                m_bordersHash.insert(border.borderKey(), border);
+                if (border.isValid())
+                    border.setBorderIndex(m_bordersList.size()-1);
+            }
+        }
+    }
+
+    if (reader.hasError())
+        qWarning()<<reader.errorString();
+
+    if (hasCount && (count != m_bordersList.size()))
+        qWarning("error read borders");
+
+    return true;
+}
+
+bool Styles::readBorder(QXmlStreamReader &reader, Format &border)
+{
+    Q_ASSERT(reader.name() == QLatin1String("border"));
+
+    const auto& attributes = reader.attributes();
+    const auto isUp = attributes.hasAttribute(QLatin1String("diagonalUp"));
+    const auto isDown = attributes.hasAttribute(QLatin1String("diagonalDown"));
+    if (isUp && isDown)
+        border.setDiagonalBorderType(Format::DiagnoalBorderBoth);
+    else if (isUp)
+        border.setDiagonalBorderType(Format::DiagonalBorderUp);
+    else if (isDown)
+        border.setDiagonalBorderType(Format::DiagonalBorderDown);
+
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("border"))) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("left") || reader.name() == QLatin1String("right")
+                    || reader.name() == QLatin1String("top") || reader.name() == QLatin1String("bottom")
+                    || reader.name() == QLatin1String("diagonal") ) {
+                Format::BorderStyle style(Format::BorderNone);
+                XlsxColor color;
+                readSubBorder(reader, reader.name().toString(), style, color);
+
+                if (reader.name() == QLatin1String("left")) {
+                    border.setLeftBorderStyle(style);
+                    if (!color.isInvalid())
+                        border.setProperty(FormatPrivate::P_Border_LeftColor, color);
+                } else if (reader.name() == QLatin1String("right")) {
+                    border.setRightBorderStyle(style);
+                    if (!color.isInvalid())
+                        border.setProperty(FormatPrivate::P_Border_RightColor, color);
+                } else if (reader.name() == QLatin1String("top")) {
+                    border.setTopBorderStyle(style);
+                    if (!color.isInvalid())
+                        border.setProperty(FormatPrivate::P_Border_TopColor, color);
+                } else if (reader.name() == QLatin1String("bottom")) {
+                    border.setBottomBorderStyle(style);
+                    if (!color.isInvalid())
+                        border.setProperty(FormatPrivate::P_Border_BottomColor, color);
+                } else if (reader.name() == QLatin1String("diagonal")) {
+                    border.setDiagonalBorderStyle(style);
+                    if (!color.isInvalid())
+                        border.setProperty(FormatPrivate::P_Border_DiagonalColor, color);
+                }
+            }
+        }
+
+        if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("border"))
+            break;
+    }
+
+    return true;
+}
+
+bool Styles::readCellStyleXfs(QXmlStreamReader &reader)
+{
+    Q_UNUSED(reader);
+    return true;
+}
+
+bool Styles::readSubBorder(QXmlStreamReader &reader, const QString &name, Format::BorderStyle &style, XlsxColor &color)
+{
+    Q_ASSERT(reader.name() == name);
+
+    static const QMap<QString, Format::BorderStyle> stylesStringsMap = {
+        {QStringLiteral("none"), Format::BorderNone},
+        {QStringLiteral("thin"), Format::BorderThin},
+        {QStringLiteral("medium"), Format::BorderMedium},
+        {QStringLiteral("dashed"), Format::BorderDashed},
+        {QStringLiteral("dotted"), Format::BorderDotted},
+        {QStringLiteral("thick"), Format::BorderThick},
+        {QStringLiteral("double"), Format::BorderDouble},
+        {QStringLiteral("hair"), Format::BorderHair},
+        {QStringLiteral("mediumDashed"), Format::BorderMediumDashed},
+        {QStringLiteral("dashDot"), Format::BorderDashDot},
+        {QStringLiteral("mediumDashDot"), Format::BorderMediumDashDot},
+        {QStringLiteral("dashDotDot"), Format::BorderDashDotDot},
+        {QStringLiteral("mediumDashDotDot"), Format::BorderMediumDashDotDot},
+        {QStringLiteral("slantDashDot"), Format::BorderSlantDashDot}
+    };
+
+    const auto& attributes = reader.attributes();
+    if (attributes.hasAttribute(QLatin1String("style"))) {
+        QString styleString = attributes.value(QLatin1String("style")).toString();
+        const auto& it = stylesStringsMap.constFind(styleString);
+        if (it != stylesStringsMap.constEnd()) {
+            //get style
+            style = it.value();
+            while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == name)) {
+                reader.readNextStartElement();
+                if (reader.tokenType() == QXmlStreamReader::StartElement) {
+                    if (reader.name() == QLatin1String("color"))
+                        color.loadFromXml(reader);
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+bool Styles::readCellXfs(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("cellXfs"));
+    const auto& attributes = reader.attributes();
+    const auto hasCount = attributes.hasAttribute(QLatin1String("count"));
+    const auto count = hasCount ? attributes.value(QLatin1String("count")).toInt() : -1;
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("cellXfs"))) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("xf")) {
+
+                Format format;
+                const auto& xfAttrs = reader.attributes();
+
+                //        qDebug()<<reader.name()<<reader.tokenString()<<" .........";
+                //        for (int i=0; i<xfAttrs.size(); ++i)
+                //            qDebug()<<"... "<<i<<" "<<xfAttrs[i].name()<<xfAttrs[i].value();
+
+                if (xfAttrs.hasAttribute(QLatin1String("numFmtId"))) {
+                    const auto numFmtIndex = xfAttrs.value(QLatin1String("numFmtId")).toInt();
+                    const auto apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyNumberFormat")).toString());
+                    if(apply) {
+                        const auto& it = m_customNumFmtIdMap.constFind(numFmtIndex);
+                        if (it == m_customNumFmtIdMap.constEnd())
+                            format.setNumberFormatIndex(numFmtIndex);
+                        else
+                            format.setNumberFormat(numFmtIndex, it.value()->formatString);
+                    }
+                }
+
+                if (xfAttrs.hasAttribute(QLatin1String("fontId"))) {
+                    const auto fontIndex = xfAttrs.value(QLatin1String("fontId")).toInt();
+                    if (fontIndex >= m_fontsList.size()) {
+                        qDebug("Error read styles.xml, cellXfs fontId");
+                    } else {
+                        const auto apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyFont")).toString());
+                        if(apply) {
+                            Format fontFormat = m_fontsList[fontIndex];
+                            for (int i=FormatPrivate::P_Font_STARTID; i<FormatPrivate::P_Font_ENDID; ++i) {
+                                if (fontFormat.hasProperty(i))
+                                    format.setProperty(i, fontFormat.property(i));
+                            }
+                        }
+                    }
+                }
+
+                if (xfAttrs.hasAttribute(QLatin1String("fillId"))) {
+                    const auto id = xfAttrs.value(QLatin1String("fillId")).toInt();
+                    if (id >= m_fillsList.size()) {
+                        qDebug("Error read styles.xml, cellXfs fillId");
+                    } else {
+
+                        // dev20 branch
+                        // NOTE: MIcrosoft Excel does not have 'applyFill' tag.
+                        //
+
+                        // bool apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyFill")).toString());
+                        // if (apply)
+
+                        {
+                            Format fillFormat = m_fillsList[id];
+                            for (int i=FormatPrivate::P_Fill_STARTID; i<FormatPrivate::P_Fill_ENDID; ++i)
+                            {
+                                if (fillFormat.hasProperty(i))
+                                    format.setProperty(i, fillFormat.property(i));
+                            }
+                        }
+
+                    }
+                }
+
+                if (xfAttrs.hasAttribute(QLatin1String("borderId"))) {
+                    const auto id = xfAttrs.value(QLatin1String("borderId")).toInt();
+                    if (id >= m_bordersList.size()) {
+                        qDebug("Error read styles.xml, cellXfs borderId");
+                    } else {
+                        const auto apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyBorder")).toString());
+                        if(apply) {
+                            Format borderFormat = m_bordersList[id];
+                            for (int i=FormatPrivate::P_Border_STARTID; i<FormatPrivate::P_Border_ENDID; ++i) {
+                                if (borderFormat.hasProperty(i))
+                                    format.setProperty(i, borderFormat.property(i));
+                            }
+                        }
+                    }
+                }
+
+                const auto apply = parseXsdBoolean(xfAttrs.value(QLatin1String("applyAlignment")).toString());
+                if(apply) {
+                    reader.readNextStartElement();
+                    if (reader.name() == QLatin1String("alignment")) {
+                        const auto& alignAttrs = reader.attributes();
+
+                        if (alignAttrs.hasAttribute(QLatin1String("horizontal"))) {
+                            static const QMap<QString, Format::HorizontalAlignment> alignStringMap = {
+                                {QStringLiteral("left"), Format::AlignLeft},
+                                {QStringLiteral("center"), Format::AlignHCenter},
+                                {QStringLiteral("right"), Format::AlignRight},
+                                {QStringLiteral("justify"), Format::AlignHJustify},
+                                {QStringLiteral("centerContinuous"), Format::AlignHMerge},
+                                {QStringLiteral("distributed"), Format::AlignHDistributed}
+                            };
+
+                            const auto& it = alignStringMap.constFind(alignAttrs.value(QLatin1String("horizontal")).toString());
+                            if (it != alignStringMap.constEnd())
+                                format.setHorizontalAlignment(it.value());
+                        }
+
+                        if (alignAttrs.hasAttribute(QLatin1String("vertical"))) {
+                            static const QMap<QString, Format::VerticalAlignment> alignStringMap = {
+                                {QStringLiteral("top"), Format::AlignTop},
+                                {QStringLiteral("center"), Format::AlignVCenter},
+                                {QStringLiteral("justify"), Format::AlignVJustify},
+                                {QStringLiteral("distributed"), Format::AlignVDistributed}
+                            };
+
+                            const auto& it = alignStringMap.constFind(alignAttrs.value(QLatin1String("vertical")).toString());
+                            if (it != alignStringMap.constEnd())
+                                format.setVerticalAlignment(it.value());
+                        }
+
+                        if (alignAttrs.hasAttribute(QLatin1String("indent"))) {
+                            const auto indent = alignAttrs.value(QLatin1String("indent")).toInt();
+                            format.setIndent(indent);
+                        }
+
+                        if (alignAttrs.hasAttribute(QLatin1String("textRotation"))) {
+                            const auto rotation = alignAttrs.value(QLatin1String("textRotation")).toInt();
+                            format.setRotation(rotation);
+                        }
+
+                        if (alignAttrs.hasAttribute(QLatin1String("wrapText")))
+                            format.setTextWrap(true);
+
+                        if (alignAttrs.hasAttribute(QLatin1String("shrinkToFit")))
+                            format.setShrinkToFit(true);
+
+                    }
+                }
+
+                addXfFormat(format, true);
+            }
+        }
+    }
+
+    if (reader.hasError())
+        qWarning()<<reader.errorString();
+
+    if (hasCount && (count != m_xf_formatsList.size()))
+        qWarning("error read CellXfs");
+
+    return true;
+}
+
+bool Styles::readDxfs(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("dxfs"));
+    const auto& attributes = reader.attributes();
+    const auto hasCount = attributes.hasAttribute(QLatin1String("count"));
+    const auto count = hasCount ? attributes.value(QLatin1String("count")).toInt() : -1;
+    while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
+                                && reader.name() == QLatin1String("dxfs"))) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("dxf"))
+                readDxf(reader);
+        }
+    }
+    if (reader.hasError())
+        qWarning()<<reader.errorString();
+
+    if (hasCount && (count != m_dxf_formatsList.size()))
+        qWarning("error read dxfs");
+
+    return true;
+}
+
+bool Styles::readDxf(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("dxf"));
+    Format format;
+    while (!reader.atEnd() && !(reader.name() == QLatin1String("dxf") && reader.tokenType() == QXmlStreamReader::EndElement)) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("numFmt")) {
+                const auto& attributes = reader.attributes();
+                const auto id = attributes.value(QLatin1String("numFmtId")).toInt();
+                QString code = attributes.value(QLatin1String("formatCode")).toString();
+                format.setNumberFormat(id, code);
+            } else if (reader.name() == QLatin1String("font")) {
+                readFont(reader, format);
+            } else if (reader.name() == QLatin1String("fill")) {
+                readFill(reader, format);
+            } else if (reader.name() == QLatin1String("border")) {
+                readBorder(reader, format);
+            }
+        }
+    }
+    addDxfFormat(format, true);
+    return true;
+}
+
+bool Styles::readColors(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("colors"));
+    while (!reader.atEnd() && !(reader.name() == QLatin1String("colors") && reader.tokenType() == QXmlStreamReader::EndElement)) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("indexedColors")) {
+                readIndexedColors(reader);
+            } else if (reader.name() == QLatin1String("mruColors")) {
+
+            }
+        }
+    }
+    return true;
+}
+
+bool Styles::readIndexedColors(QXmlStreamReader &reader)
+{
+    Q_ASSERT(reader.name() == QLatin1String("indexedColors"));
+    m_indexedColors.clear();
+    while (!reader.atEnd() && !(reader.name() == QLatin1String("indexedColors") && reader.tokenType() == QXmlStreamReader::EndElement)) {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("rgbColor")) {
+                const auto& color = reader.attributes().value(QLatin1String("rgb")).toString();
+                m_indexedColors.append(XlsxColor::fromARGBString(color));
+            }
+        }
+    }
+    if (!m_indexedColors.isEmpty())
+        m_isIndexedColorsDefault = false;
+    return true;
+}
+
+bool Styles::loadFromXmlFile(QIODevice *device)
+{
+    QXmlStreamReader reader(device);
+    while (!reader.atEnd()) {
+        QXmlStreamReader::TokenType token = reader.readNext();
+        if (token == QXmlStreamReader::StartElement) {
+            if (reader.name() == QLatin1String("numFmts")) {
+                readNumFmts(reader);
+            } else if (reader.name() == QLatin1String("fonts")) {
+                readFonts(reader);
+            } else if (reader.name() == QLatin1String("fills")) {
+                readFills(reader);
+            } else if (reader.name() == QLatin1String("borders")) {
+                readBorders(reader);
+            } else if (reader.name() == QLatin1String("cellStyleXfs")) {
+
+                readCellStyleXfs(reader);
+
+            } else if (reader.name() == QLatin1String("cellXfs")) {
+                readCellXfs(reader);
+            } else if (reader.name() == QLatin1String("cellStyles")) {
+
+                // cellStyles
+
+            } else if (reader.name() == QLatin1String("dxfs")) {
+                readDxfs(reader);
+            } else if (reader.name() == QLatin1String("colors")) {
+                readColors(reader);
+            }
+        }
+
+        if (reader.hasError()) {
+            qDebug()<<"Error when read style file: "<<reader.errorString();
+        }
+    }
+    return true;
+}
+
+QColor Styles::getColorByIndex(int idx)
+{
+    if (m_indexedColors.isEmpty()) {
+        m_indexedColors = {
+            QColor(QRgba64::fromArgb32(0x000000)), QColor(QRgba64::fromArgb32(0xFFFFFF)), QColor(QRgba64::fromArgb32(0xFF0000)), QColor(QRgba64::fromArgb32(0x00FF00)),
+            QColor(QRgba64::fromArgb32(0x0000FF)), QColor(QRgba64::fromArgb32(0xFFFF00)), QColor(QRgba64::fromArgb32(0xFF00FF)), QColor(QRgba64::fromArgb32(0x00FFFF)),
+            QColor(QRgba64::fromArgb32(0x000000)), QColor(QRgba64::fromArgb32(0xFFFFFF)), QColor(QRgba64::fromArgb32(0xFF0000)), QColor(QRgba64::fromArgb32(0x00FF00)),
+            QColor(QRgba64::fromArgb32(0x0000FF)), QColor(QRgba64::fromArgb32(0xFFFF00)), QColor(QRgba64::fromArgb32(0xFF00FF)), QColor(QRgba64::fromArgb32(0x00FFFF)),
+            QColor(QRgba64::fromArgb32(0x800000)), QColor(QRgba64::fromArgb32(0x008000)), QColor(QRgba64::fromArgb32(0x000080)), QColor(QRgba64::fromArgb32(0x808000)),
+            QColor(QRgba64::fromArgb32(0x800080)), QColor(QRgba64::fromArgb32(0x008080)), QColor(QRgba64::fromArgb32(0xC0C0C0)), QColor(QRgba64::fromArgb32(0x808080)),
+            QColor(QRgba64::fromArgb32(0x9999FF)), QColor(QRgba64::fromArgb32(0x993366)), QColor(QRgba64::fromArgb32(0xFFFFCC)), QColor(QRgba64::fromArgb32(0xCCFFFF)),
+            QColor(QRgba64::fromArgb32(0x660066)), QColor(QRgba64::fromArgb32(0xFF8080)), QColor(QRgba64::fromArgb32(0x0066CC)), QColor(QRgba64::fromArgb32(0xCCCCFF)),
+            QColor(QRgba64::fromArgb32(0x000080)), QColor(QRgba64::fromArgb32(0xFF00FF)), QColor(QRgba64::fromArgb32(0xFFFF00)), QColor(QRgba64::fromArgb32(0x00FFFF)),
+            QColor(QRgba64::fromArgb32(0x800080)), QColor(QRgba64::fromArgb32(0x800000)), QColor(QRgba64::fromArgb32(0x008080)), QColor(QRgba64::fromArgb32(0x0000FF)),
+            QColor(QRgba64::fromArgb32(0x00CCFF)), QColor(QRgba64::fromArgb32(0xCCFFFF)), QColor(QRgba64::fromArgb32(0xCCFFCC)), QColor(QRgba64::fromArgb32(0xFFFF99)),
+            QColor(QRgba64::fromArgb32(0x99CCFF)), QColor(QRgba64::fromArgb32(0xFF99CC)), QColor(QRgba64::fromArgb32(0xCC99FF)), QColor(QRgba64::fromArgb32(0xFFCC99)),
+            QColor(QRgba64::fromArgb32(0x3366FF)), QColor(QRgba64::fromArgb32(0x33CCCC)), QColor(QRgba64::fromArgb32(0x99CC00)), QColor(QRgba64::fromArgb32(0xFFCC00)),
+            QColor(QRgba64::fromArgb32(0xFF9900)), QColor(QRgba64::fromArgb32(0xFF6600)), QColor(QRgba64::fromArgb32(0x666699)), QColor(QRgba64::fromArgb32(0x969696)),
+            QColor(QRgba64::fromArgb32(0x003366)), QColor(QRgba64::fromArgb32(0x339966)), QColor(QRgba64::fromArgb32(0x003300)), QColor(QRgba64::fromArgb32(0x333300)),
+            QColor(QRgba64::fromArgb32(0x993300)), QColor(QRgba64::fromArgb32(0x993366)), QColor(QRgba64::fromArgb32(0x333399)), QColor(QRgba64::fromArgb32(0x333333)),
+        };
+        m_isIndexedColorsDefault = true;
+    }
+    if (idx < 0 || idx >= m_indexedColors.size())
+        return QColor();
+    return m_indexedColors[idx];
+}
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxtheme.cpp b/internal_system_v1/QXlsx/source/xlsxtheme.cpp
new file mode 100644
index 0000000..87f9364
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxtheme.cpp
@@ -0,0 +1,216 @@
+// 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
diff --git a/internal_system_v1/QXlsx/source/xlsxutility.cpp b/internal_system_v1/QXlsx/source/xlsxutility.cpp
new file mode 100644
index 0000000..dd8680a
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxutility.cpp
@@ -0,0 +1,291 @@
+// xlsxutility.cpp
+
+#include "xlsxutility_p.h"
+#include "xlsxcellreference.h"
+
+#include <QString>
+#include <QPoint>
+#include <QRegularExpression>
+#include <QMap>
+#include <QStringList>
+#include <QColor>
+#include <QDateTime>
+#include <QDebug>
+
+#include <cmath>
+#include <string>
+
+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)
+{
+    QDateTime dtRet; // return value
+
+    if (!is1904 && num > 60) // for mac os excel
+    {
+        num = num - 1;
+    }
+
+    qint64 msecs = static_cast<qint64>(num * 1000*60*60*24.0 + 0.5);
+    QDateTime epoch(is1904 ? QDate(1904, 1, 1): QDate(1899, 12, 31), QTime(0,0));
+    QDateTime dtOld = epoch.addMSecs(msecs);
+    dtRet = dtOld;
+
+    // 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());
+}
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxworkbook.cpp b/internal_system_v1/QXlsx/source/xlsxworkbook.cpp
new file mode 100644
index 0000000..2503679
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxworkbook.cpp
@@ -0,0 +1,740 @@
+// xlsxworkbook.cpp
+
+#include <QtGlobal>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QFile>
+#include <QBuffer>
+#include <QDir>
+#include <QtDebug>
+
+#include "xlsxworkbook.h"
+#include "xlsxworkbook_p.h"
+#include "xlsxsharedstrings_p.h"
+#include "xlsxworksheet.h"
+#include "xlsxchartsheet.h"
+#include "xlsxstyles_p.h"
+#include "xlsxformat.h"
+#include "xlsxworksheet_p.h"
+#include "xlsxformat_p.h"
+#include "xlsxmediafile_p.h"
+#include "xlsxutility_p.h"
+#include "xlsxchart.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+WorkbookPrivate::WorkbookPrivate(Workbook *q, Workbook::CreateFlag flag) :
+    AbstractOOXmlFilePrivate(q, flag)
+{
+    sharedStrings = QSharedPointer<SharedStrings> (new SharedStrings(flag));
+    styles = QSharedPointer<Styles>(new Styles(flag));
+    theme = QSharedPointer<Theme>(new 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 golbal 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 = NULL;
+    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(QSharedPointer<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 0;
+    }
+    if (!sheetName.isEmpty()) {
+        //If user given an already in-used name, we should not continue any more!
+        if (d->sheetNames.contains(sheetName))
+            return 0;
+    } 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 0;
+        }
+    }
+
+    ++d->last_sheet_id;
+
+    AbstractSheet *sheet = NULL;
+    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, QSharedPointer<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].data();
+}
+
+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;
+
+    QSharedPointer<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(QSharedPointer<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 0;
+    return d->sheets.at(index).data();
+}
+
+SharedStrings *Workbook::sharedStrings() const
+{
+    Q_D(const Workbook);
+    return d->sharedStrings.data();
+}
+
+Styles *Workbook::styles()
+{
+    Q_D(Workbook);
+    return d->styles.data();
+}
+
+Theme *Workbook::theme()
+{
+    Q_D(Workbook);
+    return d->theme.data();
+}
+
+/*!
+ * \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) {
+        QSharedPointer<AbstractSheet> sheet = d->sheets[i];
+        if (sheet->drawing())
+        ds.append(sheet->drawing());
+    }
+
+    return ds;
+}
+
+/*!
+ * \internal
+ */
+QList<QSharedPointer<AbstractSheet> > Workbook::getSheetsByTypes(AbstractSheet::SheetType type) const
+{
+    Q_D(const Workbook);
+    QList<QSharedPointer<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) {
+        QSharedPointer<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.size() > 0) {
+        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);
+                 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() + QLatin1String("/") + 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);
+
+                 QSharedPointer<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<QSharedPointer<Chart> > Workbook::chartFiles() const
+{
+    Q_D(const Workbook);
+
+    return d->chartFiles;
+}
+
+/*!
+ * \internal
+ */
+void Workbook::addChartFile(QSharedPointer<Chart> chart)
+{
+    Q_D(Workbook);
+
+    if (!d->chartFiles.contains(chart))
+        d->chartFiles.append(chart);
+}
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxworksheet.cpp b/internal_system_v1/QXlsx/source/xlsxworksheet.cpp
new file mode 100644
index 0000000..9351704
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxworksheet.cpp
@@ -0,0 +1,3083 @@
+// xlsxworksheet.cpp
+
+#include <QtGlobal>
+#include <QVariant>
+#include <QDateTime>
+#include <QDate>
+#include <QTime>
+#include <QPoint>
+#include <QFile>
+#include <QUrl>
+#include <QDebug>
+#include <QBuffer>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
+#include <QTextDocument>
+#include <QDir>
+#include <QMapIterator>
+#include <QMap>
+
+#include <cmath>
+
+#include "xlsxrichstring.h"
+#include "xlsxcellreference.h"
+#include "xlsxworksheet.h"
+#include "xlsxworksheet_p.h"
+#include "xlsxworkbook.h"
+#include "xlsxformat.h"
+#include "xlsxformat_p.h"
+#include "xlsxutility_p.h"
+#include "xlsxsharedstrings_p.h"
+#include "xlsxdrawing_p.h"
+#include "xlsxstyles_p.h"
+#include "xlsxcell.h"
+#include "xlsxcell_p.h"
+#include "xlsxcellrange.h"
+#include "xlsxconditionalformatting_p.h"
+#include "xlsxdrawinganchor_p.h"
+#include "xlsxchart.h"
+#include "xlsxcellformula.h"
+#include "xlsxcellformula_p.h"
+#include "xlsxcelllocation.h"
+
+QT_BEGIN_NAMESPACE_XLSX
+
+WorksheetPrivate::WorksheetPrivate(Worksheet *p, Worksheet::CreateFlag flag)
+: AbstractSheetPrivate(p, flag),
+  windowProtection(false),
+  showFormulas(false),
+  showGridLines(true),
+  showRowColHeaders(true),
+  showZeros(true),
+  rightToLeft(false),
+  tabSelected(false),
+  showRuler(false),
+  showOutlineSymbols(true),
+  showWhiteSpace(true),
+  urlPattern(QStringLiteral("^([fh]tt?ps?://)|(mailto:)|(file://)"))
+{
+	previous_row = 0;
+
+	outline_row_level = 0;
+	outline_col_level = 0;
+
+	default_row_height = 15;
+	default_row_zeroed = false;
+}
+
+WorksheetPrivate::~WorksheetPrivate()
+{
+}
+
+/*
+  Calculate the "spans" attribute of the <row> tag. This is an
+  XLSX optimisation and isn't strictly required. However, it
+  makes comparing files easier. The span is the same for each
+  block of 16 rows.
+ */
+void WorksheetPrivate::calculateSpans() const
+{
+	row_spans.clear();
+	int span_min = XLSX_COLUMN_MAX+1;
+	int span_max = -1;
+
+	for (int row_num = dimension.firstRow(); row_num <= dimension.lastRow(); row_num++) {
+        auto it = cellTable.constFind(row_num);
+        if (it != cellTable.constEnd()) {
+			for (int col_num = dimension.firstColumn(); col_num <= dimension.lastColumn(); col_num++) {
+                if (it->contains(col_num)) {
+					if (span_max == -1) {
+						span_min = col_num;
+						span_max = col_num;
+					} else {
+						if (col_num < span_min)
+							span_min = col_num;
+						else if (col_num > span_max)
+							span_max = col_num;
+					}
+				}
+			}
+		}
+        auto cIt = comments.constFind(row_num);
+        if (cIt != comments.constEnd()) {
+			for (int col_num = dimension.firstColumn(); col_num <= dimension.lastColumn(); col_num++) {
+                if (cIt->contains(col_num)) {
+					if (span_max == -1) {
+						span_min = col_num;
+						span_max = col_num;
+					} else {
+						if (col_num < span_min)
+							span_min = col_num;
+						else if (col_num > span_max)
+							span_max = col_num;
+					}
+				}
+			}
+		}
+
+		if (row_num%16 == 0 || row_num == dimension.lastRow()) {
+			if (span_max != -1) {
+                row_spans[row_num / 16] = QStringLiteral("%1:%2").arg(span_min).arg(span_max);
+				span_min = XLSX_COLUMN_MAX+1;
+				span_max = -1;
+			}
+		}
+	}
+}
+
+
+QString WorksheetPrivate::generateDimensionString() const
+{
+	if (!dimension.isValid())
+		return QStringLiteral("A1");
+	else
+		return dimension.toString();
+}
+
+/*
+  Check that row and col are valid and store the max and min
+  values for use in other methods/elements. The ignore_row /
+  ignore_col flags is used to indicate that we wish to perform
+  the dimension check without storing the value. The ignore
+  flags are use by setRow() and dataValidate.
+*/
+int WorksheetPrivate::checkDimensions(int row, int col, bool ignore_row, bool ignore_col)
+{
+	Q_ASSERT_X(row!=0, "checkDimensions", "row should start from 1 instead of 0");
+	Q_ASSERT_X(col!=0, "checkDimensions", "column should start from 1 instead of 0");
+
+	if (row > XLSX_ROW_MAX || row < 1 || col > XLSX_COLUMN_MAX || col < 1)
+		return -1;
+
+	if (!ignore_row) {
+		if (row < dimension.firstRow() || dimension.firstRow() == -1) dimension.setFirstRow(row);
+		if (row > dimension.lastRow()) dimension.setLastRow(row);
+	}
+	if (!ignore_col) {
+		if (col < dimension.firstColumn() || dimension.firstColumn() == -1) dimension.setFirstColumn(col);
+		if (col > dimension.lastColumn()) dimension.setLastColumn(col);
+	}
+
+	return 0;
+}
+
+/*!
+  \class Worksheet
+  \inmodule QtXlsx
+  \brief Represent one worksheet in the workbook.
+*/
+
+/*!
+ * \internal
+ */
+Worksheet::Worksheet(const QString &name, int id, Workbook *workbook, CreateFlag flag)
+	:AbstractSheet(name, id, workbook, new WorksheetPrivate(this, flag))
+{
+	if (!workbook) //For unit test propose only. Ignore the memery leak.
+		d_func()->workbook = new Workbook(flag);
+}
+
+/*!
+ * \internal
+ *
+ * Make a copy of this sheet.
+ */
+
+Worksheet *Worksheet::copy(const QString &distName, int distId) const
+{
+	Q_D(const Worksheet);
+	Worksheet *sheet = new Worksheet(distName, distId, d->workbook, F_NewFromScratch);
+	WorksheetPrivate *sheet_d = sheet->d_func();
+
+	sheet_d->dimension = d->dimension;
+
+    QMapIterator<int, QMap<int, std::shared_ptr<Cell> > > it(d->cellTable);
+    while (it.hasNext())
+    {
+		it.next();
+		int row = it.key();
+        QMapIterator<int, std::shared_ptr<Cell> > it2(it.value());
+        while (it2.hasNext())
+        {
+			it2.next();
+			int col = it2.key();
+
+            auto cell = std::make_shared<Cell>(it2.value().get());
+			cell->d_ptr->parent = sheet;
+
+			if (cell->cellType() == Cell::SharedStringType)
+				d->workbook->sharedStrings()->addSharedString(cell->d_ptr->richString);
+
+			sheet_d->cellTable[row][col] = cell;
+		}
+	}
+
+	sheet_d->merges = d->merges;
+//    sheet_d->rowsInfo = d->rowsInfo;
+//    sheet_d->colsInfo = d->colsInfo;
+//    sheet_d->colsInfoHelper = d->colsInfoHelper;
+//    sheet_d->dataValidationsList = d->dataValidationsList;
+//    sheet_d->conditionalFormattingList = d->conditionalFormattingList;
+
+	return sheet;
+}
+
+/*!
+ * Destroys this workssheet.
+ */
+Worksheet::~Worksheet()
+{
+}
+
+/*!
+ * Returns whether sheet is protected.
+ */
+bool Worksheet::isWindowProtected() const
+{
+	Q_D(const Worksheet);
+	return d->windowProtection;
+}
+
+/*!
+ * Protects/unprotects the sheet based on \a protect.
+ */
+void Worksheet::setWindowProtected(bool protect)
+{
+	Q_D(Worksheet);
+	d->windowProtection = protect;
+}
+
+/*!
+ * Return whether formulas instead of their calculated results shown in cells
+ */
+bool Worksheet::isFormulasVisible() const
+{
+	Q_D(const Worksheet);
+	return d->showFormulas;
+}
+
+/*!
+ * Show formulas in cells instead of their calculated results when \a visible is true.
+ */
+void Worksheet::setFormulasVisible(bool visible)
+{
+	Q_D(Worksheet);
+	d->showFormulas = visible;
+}
+
+/*!
+ * Return whether gridlines is shown or not.
+ */
+bool Worksheet::isGridLinesVisible() const
+{
+	Q_D(const Worksheet);
+	return d->showGridLines;
+}
+
+/*!
+ * Show or hide the gridline based on \a visible
+ */
+void Worksheet::setGridLinesVisible(bool visible)
+{
+	Q_D(Worksheet);
+	d->showGridLines = visible;
+}
+
+/*!
+ * Return whether is row and column headers is vislbe.
+ */
+bool Worksheet::isRowColumnHeadersVisible() const
+{
+	Q_D(const Worksheet);
+	return d->showRowColHeaders;
+}
+
+/*!
+ * Show or hide the row column headers based on \a visible
+ */
+void Worksheet::setRowColumnHeadersVisible(bool visible)
+{
+	Q_D(Worksheet);
+	d->showRowColHeaders = visible;
+}
+
+
+/*!
+ * Return whether the sheet is shown right-to-left or not.
+ */
+bool Worksheet::isRightToLeft() const
+{
+	Q_D(const Worksheet);
+	return d->rightToLeft;
+}
+
+/*!
+ * Enable or disable the right-to-left based on \a enable.
+ */
+void Worksheet::setRightToLeft(bool enable)
+{
+	Q_D(Worksheet);
+	d->rightToLeft = enable;
+}
+
+/*!
+ * Return whether is cells that have zero value show a zero.
+ */
+bool Worksheet::isZerosVisible() const
+{
+	Q_D(const Worksheet);
+	return d->showZeros;
+}
+
+/*!
+ * Show a zero in cells that have zero value if \a visible is true.
+ */
+void Worksheet::setZerosVisible(bool visible)
+{
+	Q_D(Worksheet);
+	d->showZeros = visible;
+}
+
+/*!
+ * Return whether this tab is selected.
+ */
+bool Worksheet::isSelected() const
+{
+	Q_D(const Worksheet);
+	return d->tabSelected;
+}
+
+/*!
+ * Select this sheet if \a select is true.
+ */
+void Worksheet::setSelected(bool select)
+{
+	Q_D(Worksheet);
+	d->tabSelected = select;
+}
+
+/*!
+ * Return whether is ruler is shown.
+ */
+bool Worksheet::isRulerVisible() const
+{
+	Q_D(const Worksheet);
+	return d->showRuler;
+
+}
+
+/*!
+ * Show or hide the ruler based on \a visible.
+ */
+void Worksheet::setRulerVisible(bool visible)
+{
+	Q_D(Worksheet);
+	d->showRuler = visible;
+
+}
+
+/*!
+ * Return whether is outline symbols is shown.
+ */
+bool Worksheet::isOutlineSymbolsVisible() const
+{
+	Q_D(const Worksheet);
+	return d->showOutlineSymbols;
+}
+
+/*!
+ * Show or hide the outline symbols based ib \a visible.
+ */
+void Worksheet::setOutlineSymbolsVisible(bool visible)
+{
+	Q_D(Worksheet);
+	d->showOutlineSymbols = visible;
+}
+
+/*!
+ * Return whether is white space is shown.
+ */
+bool Worksheet::isWhiteSpaceVisible() const
+{
+	Q_D(const Worksheet);
+	return d->showWhiteSpace;
+}
+
+/*!
+ * Show or hide the white space based on \a visible.
+ */
+void Worksheet::setWhiteSpaceVisible(bool visible)
+{
+	Q_D(Worksheet);
+	d->showWhiteSpace = visible;
+}
+
+/*!
+ * Write \a value to cell (\a row, \a column) with the \a format.
+ * Both \a row and \a column are all 1-indexed value.
+ *
+ * Returns true on success.
+ */
+bool Worksheet::write(int row, int column, const QVariant &value, const Format &format)
+{
+	Q_D(Worksheet);
+
+	if (d->checkDimensions(row, column))
+		return false;
+
+	bool ret = true;
+    if (value.isNull())
+    {
+		//Blank
+		ret = writeBlank(row, column, format);
+    }
+    else if (value.userType() == QMetaType::QString)
+    {
+		//String
+		QString token = value.toString();
+		bool ok;
+
+        if (token.startsWith(QLatin1String("=")))
+        {
+			//convert to formula
+			ret = writeFormula(row, column, CellFormula(token), format);
+        }
+        else if (d->workbook->isStringsToHyperlinksEnabled() && token.contains(d->urlPattern))
+        {
+			//convert to url
+			ret = writeHyperlink(row, column, QUrl(token));
+        }
+        else if (d->workbook->isStringsToNumbersEnabled() && (value.toDouble(&ok), ok))
+        {
+			//Try convert string to number if the flag enabled.
+			ret = writeNumeric(row, column, value.toDouble(), format);
+        }
+        else
+        {
+			//normal string now
+			ret = writeString(row, column, token, format);
+		}
+    }
+    else if (value.userType() == qMetaTypeId<RichString>())
+    {
+		ret = writeString(row, column, value.value<RichString>(), format);
+    }
+    else if (value.userType() == QMetaType::Int || value.userType() == QMetaType::UInt
+			   || value.userType() == QMetaType::LongLong || value.userType() == QMetaType::ULongLong
+               || value.userType() == QMetaType::Double || value.userType() == QMetaType::Float)
+    {
+		//Number
+
+		ret = writeNumeric(row, column, value.toDouble(), format);
+    }
+    else if (value.userType() == QMetaType::Bool)
+    {
+		//Bool
+		ret = writeBool(row,column, value.toBool(), format);
+    }
+    else if (value.userType() == QMetaType::QDateTime ) // dev67
+    {
+		//DateTime, Date
+		//  note that, QTime cann't convert to QDateTime
+		ret = writeDateTime(row, column, value.toDateTime(), format);
+    }
+    else if ( value.userType() == QMetaType::QDate ) // dev67
+    {
+        ret = writeDate(row, column, value.toDate(), format);
+    }
+    else if (value.userType() == QMetaType::QTime)
+    {
+		//Time
+		ret = writeTime(row, column, value.toTime(), format);
+    }
+    else if (value.userType() == QMetaType::QUrl)
+    {
+		//Url
+		ret = writeHyperlink(row, column, value.toUrl(), format);
+    }
+    else
+    {
+		//Wrong type
+		return false;
+	}
+
+	return ret;
+}
+
+/*!
+ * \overload
+ * Write \a value to cell \a row_column with the \a format.
+ * Both row and column are all 1-indexed value.
+ * Returns true on success.
+ */
+bool Worksheet::write(const CellReference &row_column, const QVariant &value, const Format &format)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return write(row_column.row(), row_column.column(), value, format);
+}
+
+/*!
+	\overload
+	Return the contents of the cell \a row_column.
+ */
+QVariant Worksheet::read(const CellReference &row_column) const
+{
+	if (!row_column.isValid())
+		return QVariant();
+
+	return read(row_column.row(), row_column.column());
+}
+
+/*!
+	Return the contents of the cell (\a row, \a column).
+ */
+QVariant Worksheet::read(int row, int column) const
+{
+	Q_D(const Worksheet);
+
+	Cell *cell = cellAt(row, column);
+	if (!cell)
+		return QVariant();
+
+    if (cell->hasFormula())
+    {
+        if (cell->formula().formulaType() == CellFormula::NormalType)
+        {
+			return QVariant(QLatin1String("=")+cell->formula().formulaText());
+        }
+        else if (cell->formula().formulaType() == CellFormula::SharedType)
+        {
+            if (!cell->formula().formulaText().isEmpty())
+            {
+				return QVariant(QLatin1String("=")+cell->formula().formulaText());
+            }
+            else
+            {
+                int si = cell->formula().sharedIndex();
+                const CellFormula &rootFormula = d->sharedFormulaMap[ si ];
+				CellReference rootCellRef = rootFormula.reference().topLeft();
+				QString rootFormulaText = rootFormula.formulaText();
+				QString newFormulaText = convertSharedFormula(rootFormulaText, rootCellRef, CellReference(row, column));
+				return QVariant(QLatin1String("=")+newFormulaText);
+			}
+		}
+	}
+
+    if (cell->isDateTime())
+    {
+        QVariant vDateTime = cell->dateTime();
+        return vDateTime;
+	}
+
+	return cell->value();
+}
+
+/*!
+ * Returns the cell at the given \a row_column. If there
+ * is no cell at the specified position, the function returns 0.
+ */
+Cell *Worksheet::cellAt(const CellReference &row_column) const
+{
+	if (!row_column.isValid())
+		return 0;
+
+	return cellAt(row_column.row(), row_column.column());
+}
+
+/*!
+ * Returns the cell at the given \a row and \a column. If there
+ * is no cell at the specified position, the function returns 0.
+ */
+Cell *Worksheet::cellAt(int row, int col) const
+{
+	Q_D(const Worksheet);
+    auto it = d->cellTable.constFind(row);
+    if (it == d->cellTable.constEnd())
+		return 0;
+    if (!it->contains(col))
+		return 0;
+
+    return (*it)[col].get();
+}
+
+Format WorksheetPrivate::cellFormat(int row, int col) const
+{
+    auto it = cellTable.constFind(row);
+    if (it == cellTable.constEnd())
+		return Format();
+    if (!it->contains(col))
+		return Format();
+    return (*it)[col]->format();
+}
+
+/*!
+  \overload
+  Write string \a value to the cell \a row_column with the \a format.
+
+  Returns true on success.
+ */
+bool Worksheet::writeString(const CellReference &row_column, const RichString &value, const Format &format)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeString(row_column.row(), row_column.column(), value, format);
+}
+
+/*!
+  Write string \a value to the cell (\a row, \a column) with the \a format.
+  Returns true on success.
+*/
+bool Worksheet::writeString(int row, int column, const RichString &value, const Format &format)
+{
+	Q_D(Worksheet);
+//    QString content = value.toPlainString();
+	if (d->checkDimensions(row, column))
+		return false;
+
+//    if (content.size() > d->xls_strmax) {
+//        content = content.left(d->xls_strmax);
+//        error = -2;
+//    }
+
+	d->sharedStrings()->addSharedString(value);
+	Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+	if (value.fragmentCount() == 1 && value.fragmentFormat(0).isValid())
+		fmt.mergeFormat(value.fragmentFormat(0));
+	d->workbook->styles()->addXfFormat(fmt);
+    auto cell = std::make_shared<Cell>(value.toPlainString(), Cell::SharedStringType, fmt, this);
+	cell->d_ptr->richString = value;
+	d->cellTable[row][column] = cell;
+	return true;
+}
+
+/*!
+	\overload
+	Write string \a value to the cell \a row_column with the \a format.
+ */
+bool Worksheet::writeString(const CellReference &row_column, const QString &value, const Format &format)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeString(row_column.row(), row_column.column(), value, format);
+}
+
+/*!
+	\overload
+
+	Write string \a value to the cell (\a row, \a column) with the \a format.
+	Returns true on success.
+*/
+bool Worksheet::writeString(int row, int column, const QString &value, const Format &format)
+{
+	Q_D(Worksheet);
+	if (d->checkDimensions(row, column))
+		return false;
+
+	RichString rs;
+	if (d->workbook->isHtmlToRichStringEnabled() && Qt::mightBeRichText(value))
+		rs.setHtml(value);
+	else
+		rs.addFragment(value, Format());
+
+	return writeString(row, column, rs, format);
+}
+
+/*!
+	\overload
+	Write string \a value to the cell \a row_column with the \a format
+ */
+bool Worksheet::writeInlineString(const CellReference &row_column, const QString &value, const Format &format)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeInlineString(row_column.row(), row_column.column(), value, format);
+}
+
+/*!
+	Write string \a value to the cell (\a row, \a column) with the \a format.
+	Returns true on success.
+*/
+bool Worksheet::writeInlineString(int row, int column, const QString &value, const Format &format)
+{
+	Q_D(Worksheet);
+	//int error = 0;
+	QString content = value;
+	if (d->checkDimensions(row, column))
+		return false;
+
+	if (value.size() > XLSX_STRING_MAX) {
+		content = value.left(XLSX_STRING_MAX);
+		//error = -2;
+	}
+
+	Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+	d->workbook->styles()->addXfFormat(fmt);
+    d->cellTable[row][column] = std::make_shared<Cell>(value, Cell::InlineStringType, fmt, this);
+	return true;
+}
+
+/*!
+	\overload
+	Write numeric \a value to the cell \a row_column with the \a format.
+	Returns true on success.
+ */
+bool Worksheet::writeNumeric(const CellReference &row_column, double value, const Format &format)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeNumeric(row_column.row(), row_column.column(), value, format);
+}
+
+/*!
+	Write numeric \a value to the cell (\a row, \a column) with the \a format.
+	Returns true on success.
+*/
+bool Worksheet::writeNumeric(int row, int column, double value, const Format &format)
+{
+	Q_D(Worksheet);
+	if (d->checkDimensions(row, column))
+		return false;
+
+	Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+	d->workbook->styles()->addXfFormat(fmt);
+    d->cellTable[row][column] = std::make_shared<Cell>(value, Cell::NumberType, fmt, this);
+	return true;
+}
+
+
+/*!
+	\overload
+	Write \a formula to the cell \a row_column with the \a format and \a result.
+	Returns true on success.
+ */
+bool Worksheet::writeFormula(const CellReference &row_column, const CellFormula &formula, const Format &format, double result)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeFormula(row_column.row(), row_column.column(), formula, format, result);
+}
+
+/*!
+	Write \a formula_ to the cell (\a row, \a column) with the \a format and \a result.
+	Returns true on success.
+*/
+bool Worksheet::writeFormula(int row, int column, const CellFormula &formula_, const Format &format, double result)
+{
+	Q_D(Worksheet);
+
+	if (d->checkDimensions(row, column))
+		return false;
+
+	Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+	d->workbook->styles()->addXfFormat(fmt);
+
+	CellFormula formula = formula_;
+	formula.d->ca = true;
+    if (formula.formulaType() == CellFormula::SharedType)
+    {
+		//Assign proper shared index for shared formula
+        int si = 0;
+        while ( d->sharedFormulaMap.contains(si) )
+        {
+			++si;
+        }
+		formula.d->si = si;
+		d->sharedFormulaMap[si] = formula;
+	}
+
+    auto data = std::make_shared<Cell>(result, Cell::NumberType, fmt, this);
+	data->d_ptr->formula = formula;
+	d->cellTable[row][column] = data;
+
+	CellRange range = formula.reference();
+	if (formula.formulaType() == CellFormula::SharedType) {
+		CellFormula sf(QString(), CellFormula::SharedType);
+		sf.d->si = formula.sharedIndex();
+		for (int r=range.firstRow(); r<=range.lastRow(); ++r) {
+			for (int c=range.firstColumn(); c<=range.lastColumn(); ++c) {
+				if (!(r==row && c==column)) {
+					if(Cell *cell = cellAt(r, c)) {
+						cell->d_ptr->formula = sf;
+					} else {
+                        auto newCell = std::make_shared<Cell>(result, Cell::NumberType, fmt, this);
+						newCell->d_ptr->formula = sf;
+						d->cellTable[r][c] = newCell;
+					}
+				}
+			}
+		}
+	}
+
+	return true;
+}
+
+/*!
+	\overload
+	Write a empty cell \a row_column with the \a format.
+	Returns true on success.
+ */
+bool Worksheet::writeBlank(const CellReference &row_column, const Format &format)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeBlank(row_column.row(), row_column.column(), format);
+}
+
+/*!
+	Write a empty cell (\a row, \a column) with the \a format.
+	Returns true on success.
+ */
+bool Worksheet::writeBlank(int row, int column, const Format &format)
+{
+	Q_D(Worksheet);
+	if (d->checkDimensions(row, column))
+		return false;
+
+	Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+	d->workbook->styles()->addXfFormat(fmt);
+
+	//Note: NumberType with an invalid QVariant value means blank.
+    d->cellTable[row][column] = std::make_shared<Cell>(QVariant{}, Cell::NumberType, fmt, this);
+
+	return true;
+}
+/*!
+	\overload
+	Write a bool \a value to the cell \a row_column with the \a format.
+	Returns true on success.
+ */
+bool Worksheet::writeBool(const CellReference &row_column, bool value, const Format &format)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeBool(row_column.row(), row_column.column(), value, format);
+}
+
+/*!
+	Write a bool \a value to the cell (\a row, \a column) with the \a format.
+	Returns true on success.
+ */
+bool Worksheet::writeBool(int row, int column, bool value, const Format &format)
+{
+	Q_D(Worksheet);
+	if (d->checkDimensions(row, column))
+		return false;
+
+	Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+	d->workbook->styles()->addXfFormat(fmt);
+    d->cellTable[row][column] = std::make_shared<Cell>(value, Cell::BooleanType, fmt, this);
+
+	return true;
+}
+/*!
+	\overload
+	Write a QDateTime \a dt to the cell \a row_column with the \a format.
+	Returns true on success.
+ */
+bool Worksheet::writeDateTime(const CellReference &row_column, const QDateTime &dt, const Format &format)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeDateTime(row_column.row(), row_column.column(), dt, format);
+}
+
+/*!
+	Write a QDateTime \a dt to the cell (\a row, \a column) with the \a format.
+	Returns true on success.
+ */
+bool Worksheet::writeDateTime(int row, int column, const QDateTime &dt, const Format &format)
+{
+	Q_D(Worksheet);
+	if (d->checkDimensions(row, column))
+		return false;
+
+	Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+	if (!fmt.isValid() || !fmt.isDateTimeFormat())
+		fmt.setNumberFormat(d->workbook->defaultDateFormat());
+	d->workbook->styles()->addXfFormat(fmt);
+
+	double value = datetimeToNumber(dt, d->workbook->isDate1904());
+
+    d->cellTable[row][column] = std::make_shared<Cell>(value, Cell::NumberType, fmt, this);
+
+	return true;
+}
+
+// dev67
+bool Worksheet::writeDate(const CellReference &row_column, const QDate &dt, const Format &format)
+{
+    if (!row_column.isValid())
+        return false;
+
+    return writeDate(row_column.row(), row_column.column(), dt, format);
+}
+
+// dev67
+bool Worksheet::writeDate(int row, int column, const QDate &dt, const Format &format)
+{
+    Q_D(Worksheet);
+    if (d->checkDimensions(row, column))
+        return false;
+
+    Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+
+    if (!fmt.isValid() || !fmt.isDateTimeFormat())
+        fmt.setNumberFormat(d->workbook->defaultDateFormat());
+
+    d->workbook->styles()->addXfFormat(fmt);
+
+    double value = datetimeToNumber(QDateTime(dt, QTime(0,0,0)), d->workbook->isDate1904());
+
+    d->cellTable[row][column] = std::make_shared<Cell>(value, Cell::NumberType, fmt, this);
+
+    return true;
+}
+
+/*!
+	\overload
+	Write a QTime \a t to the cell \a row_column with the \a format.
+	Returns true on success.
+ */
+bool Worksheet::writeTime(const CellReference &row_column, const QTime &t, const Format &format)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeTime(row_column.row(), row_column.column(), t, format);
+}
+
+/*!
+	Write a QTime \a t to the cell (\a row, \a column) with the \a format.
+	Returns true on success.
+ */
+bool Worksheet::writeTime(int row, int column, const QTime &t, const Format &format)
+{
+	Q_D(Worksheet);
+	if (d->checkDimensions(row, column))
+		return false;
+
+	Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+	if (!fmt.isValid() || !fmt.isDateTimeFormat())
+		fmt.setNumberFormat(QStringLiteral("hh:mm:ss"));
+	d->workbook->styles()->addXfFormat(fmt);
+
+    d->cellTable[row][column] = std::make_shared<Cell>(timeToNumber(t), Cell::NumberType, fmt, this);
+
+	return true;
+}
+
+/*!
+	\overload
+	Write a QUrl \a url to the cell \a row_column with the given \a format \a display and \a tip.
+	Returns true on success.
+ */
+bool Worksheet::writeHyperlink(const CellReference &row_column, const QUrl &url, const Format &format, const QString &display, const QString &tip)
+{
+	if (!row_column.isValid())
+		return false;
+
+	return writeHyperlink(row_column.row(), row_column.column(), url, format, display, tip);
+}
+
+/*!
+	Write a QUrl \a url to the cell (\a row, \a column) with the given \a format \a display and \a tip.
+	Returns true on success.
+ */
+bool Worksheet::writeHyperlink(int row, int column, const QUrl &url, const Format &format, const QString &display, const QString &tip)
+{
+	Q_D(Worksheet);
+	if (d->checkDimensions(row, column))
+		return false;
+
+	//int error = 0;
+
+	QString urlString = url.toString();
+
+	//Generate proper display string
+	QString displayString = display.isEmpty() ? urlString : display;
+	if (displayString.startsWith(QLatin1String("mailto:")))
+		displayString.replace(QLatin1String("mailto:"), QString());
+	if (displayString.size() > XLSX_STRING_MAX) {
+		displayString = displayString.left(XLSX_STRING_MAX);
+		//error = -2;
+	}
+
+	/*
+	  Location within target. If target is a workbook (or this workbook)
+	  this shall refer to a sheet and cell or a defined name. Can also
+	  be an HTML anchor if target is HTML file.
+
+	  c:\temp\file.xlsx#Sheet!A1
+	  http://a.com/aaa.html#aaaaa
+	*/
+	QString locationString;
+	if (url.hasFragment()) {
+		locationString = url.fragment();
+		urlString = url.toString(QUrl::RemoveFragment);
+	}
+
+	Format fmt = format.isValid() ? format : d->cellFormat(row, column);
+	//Given a default style for hyperlink
+	if (!fmt.isValid()) {
+		fmt.setVerticalAlignment(Format::AlignVCenter);
+		fmt.setFontColor(Qt::blue);
+		fmt.setFontUnderline(Format::FontUnderlineSingle);
+	}
+	d->workbook->styles()->addXfFormat(fmt);
+
+	//Write the hyperlink string as normal string.
+	d->sharedStrings()->addSharedString(displayString);
+    d->cellTable[row][column] = std::make_shared<Cell>(displayString, Cell::SharedStringType, fmt, this);
+
+	//Store the hyperlink data in a separate table
+	d->urlTable[row][column] = QSharedPointer<XlsxHyperlinkData>(new XlsxHyperlinkData(XlsxHyperlinkData::External, urlString, locationString, QString(), tip));
+
+	return true;
+}
+
+/*!
+ * Add one DataValidation \a validation to the sheet.
+ * Returns true on success.
+ */
+bool Worksheet::addDataValidation(const DataValidation &validation)
+{
+	Q_D(Worksheet);
+	if (validation.ranges().isEmpty() || validation.validationType()==DataValidation::None)
+		return false;
+
+	d->dataValidationsList.append(validation);
+	return true;
+}
+
+/*!
+ * Add one ConditionalFormatting \a cf to the sheet.
+ * Returns true on success.
+ */
+bool Worksheet::addConditionalFormatting(const ConditionalFormatting &cf)
+{
+	Q_D(Worksheet);
+	if (cf.ranges().isEmpty())
+		return false;
+
+	for (int i=0; i<cf.d->cfRules.size(); ++i) {
+        const std::shared_ptr<XlsxCfRuleData> &rule = cf.d->cfRules[i];
+		if (!rule->dxfFormat.isEmpty())
+			d->workbook->styles()->addDxfFormat(rule->dxfFormat);
+		rule->priority = 1;
+	}
+	d->conditionalFormattingList.append(cf);
+	return true;
+}
+
+/*!
+ * Insert an \a image  at the position \a row, \a column
+ * Returns true on success.
+ */
+int Worksheet::insertImage(int row, int column, const QImage &image)
+{
+	Q_D(Worksheet);
+
+    int imageIndex = 0;
+
+	if (image.isNull())
+        return imageIndex;
+
+	if (!d->drawing)
+    {
+        d->drawing = std::make_shared<Drawing>(this, F_NewFromScratch);
+    }
+
+    DrawingOneCellAnchor* anchor = new DrawingOneCellAnchor(d->drawing.get(), DrawingAnchor::Picture);
+
+	/*
+		The size are expressed as English Metric Units (EMUs).
+		EMU is 1/360 000 of centimiter.
+	*/
+	anchor->from = XlsxMarker(row, column, 0, 0);
+	float scaleX = 36e6f / std::max(1,image.dotsPerMeterX());
+	float scaleY = 36e6f / std::max(1,image.dotsPerMeterY());
+	anchor->ext = QSize( int(image.width() * scaleX), int(image.height() * scaleY) );
+
+	anchor->setObjectPicture(image);
+
+    imageIndex = anchor->getm_id();
+
+    return imageIndex;
+}
+
+bool Worksheet::getImage(int imageIndex, QImage& img)
+{
+    Q_D(Worksheet);
+
+    if( imageIndex <= (-1) )
+    {
+        return false;
+    }
+
+    if ( d->drawing == nullptr )
+    {
+        return false;
+    }
+
+    int realImageIndex = imageIndex - 1; // minus one
+
+   DrawingAnchor* danchor = d->drawing->anchors.at( realImageIndex );
+   // QSharedPointer<Drawing> // for multithread
+   if ( danchor == nullptr )
+   {
+       return false;
+   }
+
+   bool ret= danchor->getObjectPicture(img);
+   return ret;
+}
+
+bool Worksheet::getImage(int row, int column, QImage &img)
+{
+    Q_D(Worksheet);
+
+    if ( d->drawing == nullptr )
+    {
+        return false;
+    }
+
+    for(int i = 0; i < d->drawing->anchors.size(); i++)
+    {
+        if(d->drawing->anchors[i]->row() == row && d->drawing->anchors[i]->col() == column)
+        {
+            DrawingAnchor* danchor = d->drawing->anchors.at( i );
+
+            if ( danchor == nullptr )
+            {
+                return false;
+            }
+
+            bool ret= danchor->getObjectPicture(img);
+            return ret;
+        }
+    }
+    return false;
+}
+
+uint Worksheet::getImageCount()
+{
+    Q_D(Worksheet);
+
+    if ( d->drawing == nullptr )
+    {
+        return false;
+    }
+
+    int size = d->drawing->anchors.size();
+    return uint(size);
+}
+
+
+
+/*!
+ * Creates an chart with the given \a size and insert
+ * at the position \a row, \a column.
+ * The chart will be returned.
+ */
+Chart *Worksheet::insertChart(int row, int column, const QSize &size)
+{
+	Q_D(Worksheet);
+
+	if (!d->drawing)
+        d->drawing = std::make_shared<Drawing>(this, F_NewFromScratch);
+
+    DrawingOneCellAnchor *anchor = new DrawingOneCellAnchor(d->drawing.get(), DrawingAnchor::Picture);
+
+	/*
+		The size are expressed as English Metric Units (EMUs). There are
+		12,700 EMUs per point. Therefore, 12,700 * 3 /4 = 9,525 EMUs per
+		pixel
+	*/
+	anchor->from = XlsxMarker(row, column, 0, 0);
+	anchor->ext = size * 9525;
+
+	QSharedPointer<Chart> chart = QSharedPointer<Chart>(new Chart(this, F_NewFromScratch));
+	anchor->setObjectGraphicFrame(chart);
+
+	return chart.data();
+}
+
+/*!
+	Merge a \a range of cells. The first cell should contain the data and the others should
+	be blank. All cells will be applied the same style if a valid \a format is given.
+	Returns true on success.
+
+	\note All cells except the top-left one will be cleared.
+ */
+bool Worksheet::mergeCells(const CellRange &range, const Format &format)
+{
+	Q_D(Worksheet);
+	if (range.rowCount() < 2 && range.columnCount() < 2)
+		return false;
+
+	if (d->checkDimensions(range.firstRow(), range.firstColumn()))
+		return false;
+
+	if (format.isValid())
+    {
+		d->workbook->styles()->addXfFormat(format);
+    }
+
+    for (int row = range.firstRow(); row <= range.lastRow(); ++row)
+    {
+        for (int col = range.firstColumn(); col <= range.lastColumn(); ++col)
+        {
+            if (row == range.firstRow() && col == range.firstColumn())
+            {
+				Cell *cell = cellAt(row, col);
+                if (cell)
+                {
+					if (format.isValid())
+						cell->d_ptr->format = format;
+                }
+                else
+                {
+					writeBlank(row, col, format);
+				}
+            }
+            else
+            {
+				writeBlank(row, col, format);
+			}
+		}
+	}
+
+	d->merges.append(range);
+	return true;
+}
+
+/*!
+	Unmerge the cells in the \a range. Returns true on success.
+
+*/
+bool Worksheet::unmergeCells(const CellRange &range)
+{
+    Q_D(Worksheet);
+    return d->merges.removeOne(range);
+}
+
+/*!
+  Returns all the merged cells.
+*/
+QList<CellRange> Worksheet::mergedCells() const
+{
+	Q_D(const Worksheet);
+
+    // dev57
+
+    QList<CellRange> emptyList;
+
+    if ( d->type == AbstractSheet::ST_WorkSheet )
+    {
+        return d->merges;
+    }
+    else if ( d->type == AbstractSheet::ST_ChartSheet )
+    {
+    }
+    else if ( d->type == AbstractSheet::ST_DialogSheet )
+    {
+    }
+    else if ( d->type == AbstractSheet::ST_MacroSheet )
+    {
+    }
+    else
+    { // undefined
+    }
+
+    return emptyList;
+}
+
+/*!
+ * \internal
+ */
+void Worksheet::saveToXmlFile(QIODevice *device) const
+{
+	Q_D(const Worksheet);
+	d->relationships->clear();
+
+	QXmlStreamWriter writer(device);
+
+	writer.writeStartDocument(QStringLiteral("1.0"), true);
+	writer.writeStartElement(QStringLiteral("worksheet"));
+	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"));
+
+	//for Excel 2010
+	//    writer.writeAttribute("xmlns:mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
+	//    writer.writeAttribute("xmlns:x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
+	//    writer.writeAttribute("mc:Ignorable", "x14ac");
+
+	writer.writeStartElement(QStringLiteral("dimension"));
+	writer.writeAttribute(QStringLiteral("ref"), d->generateDimensionString());
+	writer.writeEndElement();//dimension
+
+	writer.writeStartElement(QStringLiteral("sheetViews"));
+	writer.writeStartElement(QStringLiteral("sheetView"));
+	if (d->windowProtection)
+		writer.writeAttribute(QStringLiteral("windowProtection"), QStringLiteral("1"));
+	if (d->showFormulas)
+		writer.writeAttribute(QStringLiteral("showFormulas"), QStringLiteral("1"));
+	if (!d->showGridLines)
+		writer.writeAttribute(QStringLiteral("showGridLines"), QStringLiteral("0"));
+	if (!d->showRowColHeaders)
+		writer.writeAttribute(QStringLiteral("showRowColHeaders"), QStringLiteral("0"));
+	if (!d->showZeros)
+		writer.writeAttribute(QStringLiteral("showZeros"), QStringLiteral("0"));
+	if (d->rightToLeft)
+		writer.writeAttribute(QStringLiteral("rightToLeft"), QStringLiteral("1"));
+	if (d->tabSelected)
+		writer.writeAttribute(QStringLiteral("tabSelected"), QStringLiteral("1"));
+	if (!d->showRuler)
+		writer.writeAttribute(QStringLiteral("showRuler"), QStringLiteral("0"));
+	if (!d->showOutlineSymbols)
+		writer.writeAttribute(QStringLiteral("showOutlineSymbols"), QStringLiteral("0"));
+	if (!d->showWhiteSpace)
+		writer.writeAttribute(QStringLiteral("showWhiteSpace"), QStringLiteral("0"));
+	writer.writeAttribute(QStringLiteral("workbookViewId"), QStringLiteral("0"));
+	writer.writeEndElement();//sheetView
+	writer.writeEndElement();//sheetViews
+
+	writer.writeStartElement(QStringLiteral("sheetFormatPr"));
+	writer.writeAttribute(QStringLiteral("defaultRowHeight"), QString::number(d->default_row_height));
+	if (d->default_row_height != 15)
+		writer.writeAttribute(QStringLiteral("customHeight"), QStringLiteral("1"));
+	if (d->default_row_zeroed)
+		writer.writeAttribute(QStringLiteral("zeroHeight"), QStringLiteral("1"));
+	if (d->outline_row_level)
+		writer.writeAttribute(QStringLiteral("outlineLevelRow"), QString::number(d->outline_row_level));
+	if (d->outline_col_level)
+		writer.writeAttribute(QStringLiteral("outlineLevelCol"), QString::number(d->outline_col_level));
+	//for Excel 2010
+	//    writer.writeAttribute("x14ac:dyDescent", "0.25");
+	writer.writeEndElement();//sheetFormatPr
+
+    if (!d->colsInfo.isEmpty())
+    {
+		writer.writeStartElement(QStringLiteral("cols"));
+		QMapIterator<int, QSharedPointer<XlsxColumnInfo> > it(d->colsInfo);
+        while (it.hasNext())
+        {
+			it.next();
+			QSharedPointer<XlsxColumnInfo> col_info = it.value();
+			writer.writeStartElement(QStringLiteral("col"));
+			writer.writeAttribute(QStringLiteral("min"), QString::number(col_info->firstColumn));
+			writer.writeAttribute(QStringLiteral("max"), QString::number(col_info->lastColumn));
+			if (col_info->width)
+				writer.writeAttribute(QStringLiteral("width"), QString::number(col_info->width, 'g', 15));
+			if (!col_info->format.isEmpty())
+				writer.writeAttribute(QStringLiteral("style"), QString::number(col_info->format.xfIndex()));
+			if (col_info->hidden)
+				writer.writeAttribute(QStringLiteral("hidden"), QStringLiteral("1"));
+			if (col_info->width)
+				writer.writeAttribute(QStringLiteral("customWidth"), QStringLiteral("1"));
+			if (col_info->outlineLevel)
+				writer.writeAttribute(QStringLiteral("outlineLevel"), QString::number(col_info->outlineLevel));
+			if (col_info->collapsed)
+				writer.writeAttribute(QStringLiteral("collapsed"), QStringLiteral("1"));
+			writer.writeEndElement();//col
+		}
+		writer.writeEndElement();//cols
+	}
+
+	writer.writeStartElement(QStringLiteral("sheetData"));
+	if (d->dimension.isValid())
+		d->saveXmlSheetData(writer);
+	writer.writeEndElement();//sheetData
+
+	d->saveXmlMergeCells(writer);
+    for (const ConditionalFormatting &cf : d->conditionalFormattingList)
+		cf.saveToXml(writer);
+	d->saveXmlDataValidations(writer);
+
+    //{{ liufeijin :  write  pagesettings  add by liufeijin 20181028
+
+    // fixed by j2doll [dev18]
+    // NOTE: empty element is not problem. but, empty structure of element is not parsed by Excel.
+
+    // pageMargins
+    if ( false == d->PMleft.isEmpty() &&
+         false == d->PMright.isEmpty() &&
+         false == d->PMtop.isEmpty() &&
+         false == d->PMbotton.isEmpty() &&
+         false == d->PMheader.isEmpty() &&
+         false == d->PMfooter.isEmpty()
+         )
+    {
+        writer.writeStartElement(QStringLiteral("pageMargins"));
+
+        writer.writeAttribute(QStringLiteral("left"),   d->PMleft );
+        writer.writeAttribute(QStringLiteral("right"),  d->PMright );
+        writer.writeAttribute(QStringLiteral("top"),    d->PMtop );
+        writer.writeAttribute(QStringLiteral("bottom"), d->PMbotton );
+        writer.writeAttribute(QStringLiteral("header"), d->PMheader );
+        writer.writeAttribute(QStringLiteral("footer"), d->PMfooter );
+
+        writer.writeEndElement(); // pageMargins
+    }
+
+    // dev57
+    if ( !d->Prid.isEmpty() )
+    {
+        writer.writeStartElement(QStringLiteral("pageSetup")); // pageSetup
+
+        writer.writeAttribute(QStringLiteral("r:id"), d->Prid);
+
+        if ( !d->PverticalDpi.isEmpty() )
+        {
+            writer.writeAttribute(QStringLiteral("verticalDpi"), d->PverticalDpi);
+        }
+
+        if ( !d->PhorizontalDpi.isEmpty() )
+        {
+            writer.writeAttribute(QStringLiteral("horizontalDpi"), d->PhorizontalDpi);
+        }
+
+        if ( !d->PuseFirstPageNumber.isEmpty() )
+        {
+            writer.writeAttribute(QStringLiteral("useFirstPageNumber"), d->PuseFirstPageNumber);
+        }
+
+        if ( !d->PfirstPageNumber.isEmpty() )
+        {
+            writer.writeAttribute(QStringLiteral("firstPageNumber"), d->PfirstPageNumber);
+        }
+
+        if ( !d->Pscale.isEmpty() )
+        {
+            writer.writeAttribute(QStringLiteral("scale"), d->Pscale);
+        }
+
+        if ( !d->PpaperSize.isEmpty() )
+        {
+            writer.writeAttribute(QStringLiteral("paperSize"), d->PpaperSize);
+        }
+
+        if ( !d->Porientation.isEmpty() )
+        {
+            writer.writeAttribute(QStringLiteral("orientation"), d->Porientation);
+        }
+
+        if(!d->Pcopies.isEmpty())
+        {
+            writer.writeAttribute(QStringLiteral("copies"), d->Pcopies);
+        }
+
+        writer.writeEndElement(); // pageSetup
+
+    } // if ( !d->Prid.isEmpty() )
+
+    // headerFooter
+    if( !(d->ModdHeader.isNull()) ||
+        !(d->MoodFooter.isNull()) )
+    {
+        writer.writeStartElement(QStringLiteral("headerFooter")); // headerFooter
+
+        if ( !d->MoodalignWithMargins.isEmpty() )
+        {
+            writer.writeAttribute(QStringLiteral("alignWithMargins"), d->MoodalignWithMargins);
+        }
+
+        if ( !d->ModdHeader.isNull() )
+        {
+            writer.writeStartElement(QStringLiteral("oddHeader"));
+            writer.writeCharacters(d->ModdHeader);
+            writer.writeEndElement(); // oddHeader
+        }
+
+        if ( !d->MoodFooter.isNull() )
+        {
+            writer.writeTextElement(QStringLiteral("oddFooter"), d->MoodFooter);
+        }
+
+        writer.writeEndElement(); // headerFooter
+    }
+
+	d->saveXmlHyperlinks(writer);
+	d->saveXmlDrawings(writer);
+
+    writer.writeEndElement(); // worksheet
+	writer.writeEndDocument();
+}
+
+//{{ liufeijin
+bool Worksheet::setStartPage(int spagen)
+{
+    Q_D(Worksheet);
+
+    d->PfirstPageNumber=QString::number(spagen);
+
+    return true;
+}
+//}}
+
+void WorksheetPrivate::saveXmlSheetData(QXmlStreamWriter &writer) const
+{
+	calculateSpans();
+    for (int row_num = dimension.firstRow(); row_num <= dimension.lastRow(); row_num++)
+    {
+        auto ctIt = cellTable.constFind(row_num);
+        auto riIt = rowsInfo.constFind(row_num);
+        if (ctIt == cellTable.constEnd() && riIt == rowsInfo.constEnd() && !comments.contains(row_num))
+        {
+			//Only process rows with cell data / comments / formatting
+			continue;
+		}
+
+		int span_index = (row_num-1) / 16;
+		QString span;
+        auto rsIt = row_spans.constFind(span_index);
+        if (rsIt != row_spans.constEnd())
+            span = rsIt.value();
+
+		writer.writeStartElement(QStringLiteral("row"));
+		writer.writeAttribute(QStringLiteral("r"), QString::number(row_num));
+
+		if (!span.isEmpty())
+			writer.writeAttribute(QStringLiteral("spans"), span);
+
+        if (riIt != rowsInfo.constEnd())
+        {
+            QSharedPointer<XlsxRowInfo> rowInfo = riIt.value();
+            if (!rowInfo->format.isEmpty())
+            {
+				writer.writeAttribute(QStringLiteral("s"), QString::number(rowInfo->format.xfIndex()));
+				writer.writeAttribute(QStringLiteral("customFormat"), QStringLiteral("1"));
+			}
+
+			//!Todo: support customHeight from info struct
+			//!Todo: where does this magic number '15' come from?
+			if (rowInfo->customHeight) {
+				writer.writeAttribute(QStringLiteral("ht"), QString::number(rowInfo->height));
+				writer.writeAttribute(QStringLiteral("customHeight"), QStringLiteral("1"));
+			} else {
+				writer.writeAttribute(QStringLiteral("customHeight"), QStringLiteral("0"));
+			}
+
+			if (rowInfo->hidden)
+				writer.writeAttribute(QStringLiteral("hidden"), QStringLiteral("1"));
+			if (rowInfo->outlineLevel > 0)
+				writer.writeAttribute(QStringLiteral("outlineLevel"), QString::number(rowInfo->outlineLevel));
+			if (rowInfo->collapsed)
+				writer.writeAttribute(QStringLiteral("collapsed"), QStringLiteral("1"));
+		}
+
+		//Write cell data if row contains filled cells
+        if (ctIt != cellTable.constEnd())
+        {
+            for (int col_num = dimension.firstColumn(); col_num <= dimension.lastColumn(); col_num++)
+            {
+                if (ctIt->contains(col_num))
+                {
+                    saveXmlCellData(writer, row_num, col_num, (*ctIt)[col_num]);
+				}
+			}
+		}
+		writer.writeEndElement(); //row
+	}
+}
+
+void WorksheetPrivate::saveXmlCellData(QXmlStreamWriter &writer, int row, int col, std::shared_ptr<Cell> cell) const
+{
+    Q_Q(const Worksheet);
+
+	//This is the innermost loop so efficiency is important.
+	QString cell_pos = CellReference(row, col).toString();
+
+	writer.writeStartElement(QStringLiteral("c"));
+	writer.writeAttribute(QStringLiteral("r"), cell_pos);
+
+    QMap<int, QSharedPointer<XlsxRowInfo> >::ConstIterator rIt;
+    QMap<int, QSharedPointer<XlsxColumnInfo> >::ConstIterator cIt;
+
+	//Style used by the cell, row or col
+	if (!cell->format().isEmpty())
+		writer.writeAttribute(QStringLiteral("s"), QString::number(cell->format().xfIndex()));
+    else if ((rIt = rowsInfo.constFind(row)) != rowsInfo.constEnd() && !(*rIt)->format.isEmpty())
+        writer.writeAttribute(QStringLiteral("s"), QString::number((*rIt)->format.xfIndex()));
+    else if ((cIt = colsInfoHelper.constFind(col)) != colsInfoHelper.constEnd() && !(*cIt)->format.isEmpty())
+        writer.writeAttribute(QStringLiteral("s"), QString::number((*cIt)->format.xfIndex()));
+
+    if (cell->cellType() == Cell::SharedStringType) // 's'
+    {
+		int sst_idx;
+		if (cell->isRichString())
+			sst_idx = sharedStrings()->getSharedStringIndex(cell->d_ptr->richString);
+		else
+			sst_idx = sharedStrings()->getSharedStringIndex(cell->value().toString());
+
+		writer.writeAttribute(QStringLiteral("t"), QStringLiteral("s"));
+		writer.writeTextElement(QStringLiteral("v"), QString::number(sst_idx));
+    }
+    else if (cell->cellType() == Cell::InlineStringType) // 'inlineStr'
+    {
+		writer.writeAttribute(QStringLiteral("t"), QStringLiteral("inlineStr"));
+		writer.writeStartElement(QStringLiteral("is"));
+        if (cell->isRichString())
+        {
+			//Rich text string
+			RichString string = cell->d_ptr->richString;
+            for (int i=0; i<string.fragmentCount(); ++i)
+            {
+				writer.writeStartElement(QStringLiteral("r"));
+                if (string.fragmentFormat(i).hasFontData())
+                {
+					writer.writeStartElement(QStringLiteral("rPr"));
+					//:Todo
+					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 string = cell->value().toString();
+			if (isSpaceReserveNeeded(string))
+				writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
+			writer.writeCharacters(string);
+			writer.writeEndElement(); // t
+		}
+		writer.writeEndElement();//is
+    }
+    else if (cell->cellType() == Cell::NumberType) // 'n'
+    {
+        writer.writeAttribute(QStringLiteral("t"), QStringLiteral("n")); // dev67
+
+        if (cell->hasFormula())
+        {
+            QString strFormula = cell->formula().d->formula;
+            Q_UNUSED(strFormula);
+            cell->formula().saveToXml(writer);
+        }
+
+        if (cell->value().isValid())
+        {   //note that, invalid value means 'v' is blank
+			double value = cell->value().toDouble();
+			writer.writeTextElement(QStringLiteral("v"), QString::number(value, 'g', 15));
+		}
+    }
+    else if (cell->cellType() == Cell::StringType) // 'str'
+    {
+		writer.writeAttribute(QStringLiteral("t"), QStringLiteral("str"));
+		if (cell->hasFormula())
+			cell->formula().saveToXml(writer);
+
+		writer.writeTextElement(QStringLiteral("v"), cell->value().toString());
+    }
+    else if (cell->cellType() == Cell::BooleanType) // 'b'
+    {
+		writer.writeAttribute(QStringLiteral("t"), QStringLiteral("b"));
+
+        // dev34
+
+        if (cell->hasFormula())
+        {
+            QString strFormula = cell->formula().d->formula;
+            Q_UNUSED(strFormula);
+            cell->formula().saveToXml(writer);
+        }
+
+		writer.writeTextElement(QStringLiteral("v"), cell->value().toBool() ? QStringLiteral("1") : QStringLiteral("0"));
+	}
+    else if (cell->cellType() == Cell::DateType) // 'd'
+    {
+        // dev67
+
+         double num = cell->value().toDouble();
+         bool is1904 = q->workbook()->isDate1904();
+         if (!is1904 && num > 60) // for mac os excel
+         {
+             num = num - 1;
+         }
+
+         // number type. see for 18.18.11 ST_CellType (Cell Type) more information.
+         writer.writeAttribute(QStringLiteral("t"), QStringLiteral("n"));
+         writer.writeTextElement(QStringLiteral("v"), cell->value().toString() );
+
+    }
+    else if (cell->cellType() == Cell::ErrorType) // 'e'
+    {
+        writer.writeAttribute(QStringLiteral("t"), QStringLiteral("e"));
+        writer.writeTextElement(QStringLiteral("v"), cell->value().toString() );
+    }
+    else // if (cell->cellType() == Cell::CustomType)
+    {
+        // custom type
+
+        if (cell->hasFormula())
+        {
+            QString strFormula = cell->formula().d->formula;
+            Q_UNUSED(strFormula);
+            cell->formula().saveToXml(writer);
+        }
+
+        if (cell->value().isValid())
+        {   //note that, invalid value means 'v' is blank
+            double value = cell->value().toDouble();
+            writer.writeTextElement(QStringLiteral("v"), QString::number(value, 'g', 15));
+        }
+    }
+
+    writer.writeEndElement(); // c
+}
+
+void WorksheetPrivate::saveXmlMergeCells(QXmlStreamWriter &writer) const
+{
+	if (merges.isEmpty())
+		return;
+
+	writer.writeStartElement(QStringLiteral("mergeCells"));
+	writer.writeAttribute(QStringLiteral("count"), QString::number(merges.size()));
+
+    for (const CellRange &range : merges)
+    {
+		writer.writeEmptyElement(QStringLiteral("mergeCell"));
+		writer.writeAttribute(QStringLiteral("ref"), range.toString());
+	}
+
+	writer.writeEndElement(); //mergeCells
+}
+
+void WorksheetPrivate::saveXmlDataValidations(QXmlStreamWriter &writer) const
+{
+	if (dataValidationsList.isEmpty())
+		return;
+
+	writer.writeStartElement(QStringLiteral("dataValidations"));
+	writer.writeAttribute(QStringLiteral("count"), QString::number(dataValidationsList.size()));
+
+    for (const DataValidation &validation : dataValidationsList)
+		validation.saveToXml(writer);
+
+	writer.writeEndElement(); //dataValidations
+}
+
+void WorksheetPrivate::saveXmlHyperlinks(QXmlStreamWriter &writer) const
+{
+	if (urlTable.isEmpty())
+		return;
+
+	writer.writeStartElement(QStringLiteral("hyperlinks"));
+    QMapIterator<int, QMap< int, QSharedPointer<XlsxHyperlinkData> > > it(urlTable);
+
+    while (it.hasNext())
+    {
+		it.next();
+		int row = it.key();
+        QMapIterator< int, QSharedPointer<XlsxHyperlinkData> > it2(it.value());
+
+        while (it2.hasNext())
+        {
+			it2.next();
+			int col = it2.key();
+			QSharedPointer<XlsxHyperlinkData> data = it2.value();
+			QString ref = CellReference(row, col).toString();
+
+            // dev57
+            // writer.writeEmptyElement(QStringLiteral("hyperlink"));
+            writer.writeStartElement(QStringLiteral("hyperlink"));
+
+            writer.writeAttribute(QStringLiteral("ref"), ref); // required field
+
+            if ( data->linkType == XlsxHyperlinkData::External )
+            {
+                // Update relationships
+				relationships->addWorksheetRelationship(QStringLiteral("/hyperlink"), data->target, QStringLiteral("External"));
+
+                writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(relationships->count()));
+			}
+
+			if (!data->location.isEmpty())
+            {
+				writer.writeAttribute(QStringLiteral("location"), data->location);
+            }
+
+			if (!data->display.isEmpty())
+            {
+				writer.writeAttribute(QStringLiteral("display"), data->display);
+            }
+
+			if (!data->tooltip.isEmpty())
+            {
+				writer.writeAttribute(QStringLiteral("tooltip"), data->tooltip);
+            }
+
+            // dev57
+            writer.writeEndElement(); // hyperlink
+		}
+	}
+
+    writer.writeEndElement(); // hyperlinks
+}
+
+void WorksheetPrivate::saveXmlDrawings(QXmlStreamWriter &writer) const
+{
+	if (!drawing)
+		return;
+
+    int idx = workbook->drawings().indexOf(drawing.get());
+    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(relationships->count()));
+}
+
+void WorksheetPrivate::splitColsInfo(int colFirst, int colLast)
+{
+	// Split current columnInfo, for example, if "A:H" has been set,
+	// we are trying to set "B:D", there should be "A", "B:D", "E:H".
+	// This will be more complex if we try to set "C:F" after "B:D".
+	{
+		QMapIterator<int, QSharedPointer<XlsxColumnInfo> > it(colsInfo);
+		while (it.hasNext()) {
+			it.next();
+			QSharedPointer<XlsxColumnInfo> info = it.value();
+			if (colFirst > info->firstColumn && colFirst <= info->lastColumn) {
+				//split the range,
+				QSharedPointer<XlsxColumnInfo> info2(new XlsxColumnInfo(*info));
+				info->lastColumn = colFirst - 1;
+				info2->firstColumn = colFirst;
+				colsInfo.insert(colFirst, info2);
+				for (int c = info2->firstColumn; c <= info2->lastColumn; ++c)
+					colsInfoHelper[c] = info2;
+
+				break;
+			}
+		}
+	}
+	{
+		QMapIterator<int, QSharedPointer<XlsxColumnInfo> > it(colsInfo);
+		while (it.hasNext()) {
+			it.next();
+			QSharedPointer<XlsxColumnInfo> info = it.value();
+			if (colLast >= info->firstColumn && colLast < info->lastColumn) {
+				QSharedPointer<XlsxColumnInfo> info2(new XlsxColumnInfo(*info));
+				info->lastColumn = colLast;
+				info2->firstColumn = colLast + 1;
+				colsInfo.insert(colLast + 1, info2);
+				for (int c = info2->firstColumn; c <= info2->lastColumn; ++c)
+					colsInfoHelper[c] = info2;
+
+				break;
+			}
+		}
+	}
+}
+
+bool WorksheetPrivate::isColumnRangeValid(int colFirst, int colLast)
+{
+	bool ignore_row = true;
+	bool ignore_col = false;
+
+	if (colFirst > colLast)
+		return false;
+
+	if (checkDimensions(1, colLast, ignore_row, ignore_col))
+		return false;
+	if (checkDimensions(1, colFirst, ignore_row, ignore_col))
+		return false;
+
+	return true;
+}
+
+QList<int> WorksheetPrivate ::getColumnIndexes(int colFirst, int colLast)
+{
+	splitColsInfo(colFirst, colLast);
+
+	QList<int> nodes;
+	nodes.append(colFirst);
+    for (int col = colFirst; col <= colLast; ++col)
+    {
+        auto it = colsInfo.constFind(col);
+        if (it != colsInfo.constEnd())
+        {
+			if (nodes.last() != col)
+				nodes.append(col);
+
+            int nextCol = (*it)->lastColumn + 1;
+			if (nextCol <= colLast)
+				nodes.append(nextCol);
+		}
+	}
+
+	return nodes;
+}
+
+/*!
+  Sets width in characters of a \a range of columns to \a width.
+  Returns true on success.
+ */
+bool Worksheet::setColumnWidth(const CellRange &range, double width)
+{
+	if (!range.isValid())
+		return false;
+
+	return setColumnWidth(range.firstColumn(), range.lastColumn(), width);
+}
+
+/*!
+  Sets format property of a \a range of columns to \a format. Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Worksheet::setColumnFormat(const CellRange& range, const Format &format)
+{
+	if (!range.isValid())
+		return false;
+
+	return setColumnFormat(range.firstColumn(), range.lastColumn(), format);
+}
+
+/*!
+  Sets hidden property of a \a range of columns to \a hidden. Columns are 1-indexed.
+  Hidden columns are not visible.
+  Returns true on success.
+ */
+bool Worksheet::setColumnHidden(const CellRange &range, bool hidden)
+{
+	if (!range.isValid())
+		return false;
+
+	return setColumnHidden(range.firstColumn(), range.lastColumn(), hidden);
+}
+
+/*!
+  Sets width in characters for columns [\a colFirst, \a colLast] to \a width.
+  Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Worksheet::setColumnWidth(int colFirst, int colLast, double width)
+{
+	Q_D(Worksheet);
+
+    const QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(colFirst, colLast);
+    for (const QSharedPointer<XlsxColumnInfo> &columnInfo : columnInfoList)
+    {
+	   columnInfo->width = width;
+    }
+
+	return (columnInfoList.count() > 0);
+}
+
+/*!
+  Sets format property of a range of columns [\a colFirst, \a colLast] to \a format.
+  Columns are 1-indexed.
+  Returns true on success.
+ */
+bool Worksheet::setColumnFormat(int colFirst, int colLast, const Format &format)
+{
+	Q_D(Worksheet);
+
+    const QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(colFirst, colLast);
+    for (const QSharedPointer<XlsxColumnInfo> &columnInfo : columnInfoList)
+	   columnInfo->format = format;
+
+	if(columnInfoList.count() > 0) {
+	   d->workbook->styles()->addXfFormat(format);
+	   return true;
+	}
+
+	return false;
+}
+
+/*!
+  Sets hidden property of a range of columns [\a colFirst, \a colLast] to \a hidden.
+  Columns are 1-indexed. Returns true on success.
+ */
+bool Worksheet::setColumnHidden(int colFirst, int colLast, bool hidden)
+{
+	Q_D(Worksheet);
+
+    const QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(colFirst, colLast);
+    for (const QSharedPointer<XlsxColumnInfo> &columnInfo : columnInfoList)
+	   columnInfo->hidden = hidden;
+
+	return (columnInfoList.count() > 0);
+}
+
+/*!
+  Returns width of the \a column in characters of the normal font. Columns are 1-indexed.
+ */
+double Worksheet::columnWidth(int column)
+{
+	Q_D(Worksheet);
+
+    QList< QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(column, column);
+
+    // [dev54]
+    if ( columnInfoList.size() == 0 )
+    {
+        // column information is not found
+        // qDebug() << "[debug]" << __FUNCTION__ <<  "column (info) is not found. " << column;
+    }
+
+	if (columnInfoList.count() == 1)
+    {
+        // column information is found
+        // qDebug() << "[debug]" << __FUNCTION__ <<  "column (info) is found. " << column << oneColWidth;
+        double oneColWidth = columnInfoList.at(0)->width;
+        bool isSetWidth = columnInfoList.at(0)->isSetWidth;
+        if ( isSetWidth )
+        {
+            return oneColWidth;
+        }
+    }
+
+    // use default width
+    double defaultColWidth = d->sheetFormatProps.defaultColWidth;
+    return defaultColWidth;
+}
+
+/*!
+  Returns formatting of the \a column. Columns are 1-indexed.
+ */
+Format Worksheet::columnFormat(int column)
+{
+	Q_D(Worksheet);
+
+	QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(column, column);
+	if (columnInfoList.count() == 1)
+	   return columnInfoList.at(0)->format;
+
+	return Format();
+}
+
+/*!
+  Returns true if \a column is hidden. Columns are 1-indexed.
+ */
+bool Worksheet::isColumnHidden(int column)
+{
+	Q_D(Worksheet);
+
+	QList <QSharedPointer<XlsxColumnInfo> > columnInfoList = d->getColumnInfoList(column, column);
+	if (columnInfoList.count() == 1)
+	   return columnInfoList.at(0)->hidden;
+
+	return false;
+}
+
+/*!
+  Sets the \a height of the rows including and between \a rowFirst and \a rowLast.
+  Row height measured in point size.
+  Rows are 1-indexed.
+
+  Returns true if success.
+*/
+bool Worksheet::setRowHeight(int rowFirst,int rowLast, double height)
+{
+	Q_D(Worksheet);
+
+    const QList <QSharedPointer<XlsxRowInfo> > rowInfoList = d->getRowInfoList(rowFirst,rowLast);
+    for (const QSharedPointer<XlsxRowInfo> &rowInfo : rowInfoList) {
+		rowInfo->height = height;
+		rowInfo->customHeight = true;
+	}
+
+	return rowInfoList.count() > 0;
+}
+
+/*!
+  Sets the \a format of the rows including and between \a rowFirst and \a rowLast.
+  Rows are 1-indexed.
+
+  Returns true if success.
+*/
+bool Worksheet::setRowFormat(int rowFirst,int rowLast, const Format &format)
+{
+	Q_D(Worksheet);
+
+    const QList <QSharedPointer<XlsxRowInfo> > rowInfoList = d->getRowInfoList(rowFirst,rowLast);
+    for (const QSharedPointer<XlsxRowInfo> &rowInfo : rowInfoList)
+		rowInfo->format = format;
+
+	d->workbook->styles()->addXfFormat(format);
+	return rowInfoList.count() > 0;
+}
+
+/*!
+  Sets the \a hidden proeprty of the rows including and between \a rowFirst and \a rowLast.
+  Rows are 1-indexed. If hidden is true rows will not be visible.
+
+  Returns true if success.
+*/
+bool Worksheet::setRowHidden(int rowFirst,int rowLast, bool hidden)
+{
+	Q_D(Worksheet);
+
+    const QList <QSharedPointer<XlsxRowInfo> > rowInfoList = d->getRowInfoList(rowFirst,rowLast);
+    for (const QSharedPointer<XlsxRowInfo> &rowInfo : rowInfoList)
+		rowInfo->hidden = hidden;
+
+	return rowInfoList.count() > 0;
+}
+
+/*!
+ Returns height of \a row in points.
+*/
+double Worksheet::rowHeight(int row)
+{
+	Q_D(Worksheet);
+    const int min_col = d->dimension.isValid() ? d->dimension.firstColumn() : 1;
+
+    auto it = d->rowsInfo.constFind(row);
+    if (d->checkDimensions(row, min_col, false, true) || it == d->rowsInfo.constEnd())
+    {
+		return d->sheetFormatProps.defaultRowHeight; //return default on invalid row
+    }
+
+    return (*it)->height;
+}
+
+/*!
+ Returns format of \a row.
+*/
+Format Worksheet::rowFormat(int row)
+{
+	Q_D(Worksheet);
+    const int min_col = d->dimension.isValid() ? d->dimension.firstColumn() : 1;
+    auto it = d->rowsInfo.constFind(row);
+    if (d->checkDimensions(row, min_col, false, true) || it == d->rowsInfo.constEnd())
+		return Format(); //return default on invalid row
+
+    return (*it)->format;
+}
+
+/*!
+ Returns true if \a row is hidden.
+*/
+bool Worksheet::isRowHidden(int row)
+{
+	Q_D(Worksheet);
+    const int min_col = d->dimension.isValid() ? d->dimension.firstColumn() : 1;
+    auto it = d->rowsInfo.constFind(row);
+    if (d->checkDimensions(row, min_col, false, true) || it == d->rowsInfo.constEnd())
+		return false; //return default on invalid row
+
+    return (*it)->hidden;
+}
+
+/*!
+   Groups rows from \a rowFirst to \a rowLast with the given \a collapsed.
+
+   Returns false if error occurs.
+ */
+bool Worksheet::groupRows(int rowFirst, int rowLast, bool collapsed)
+{
+	Q_D(Worksheet);
+
+	for (int row=rowFirst; row<=rowLast; ++row) {
+        auto it = d->rowsInfo.find(row);
+        if (it != d->rowsInfo.end()) {
+            (*it)->outlineLevel += 1;
+		} else {
+			QSharedPointer<XlsxRowInfo> info(new XlsxRowInfo);
+			info->outlineLevel += 1;
+            it = d->rowsInfo.insert(row, info);
+		}
+		if (collapsed)
+            (*it)->hidden = true;
+	}
+	if (collapsed) {
+        auto it = d->rowsInfo.find(rowLast+1);
+        if (it == d->rowsInfo.end())
+            it = d->rowsInfo.insert(rowLast+1, QSharedPointer<XlsxRowInfo>(new XlsxRowInfo));
+        (*it)->collapsed = true;
+	}
+	return true;
+}
+
+/*!
+	\overload
+
+	Groups columns with the given \a range and \a collapsed.
+ */
+bool Worksheet::groupColumns(const CellRange &range, bool collapsed)
+{
+	if (!range.isValid())
+		return false;
+
+	return groupColumns(range.firstColumn(), range.lastColumn(), collapsed);
+}
+
+/*!
+   Groups columns from \a colFirst to \a colLast with the given \a collapsed.
+   Returns false if error occurs.
+*/
+bool Worksheet::groupColumns(int colFirst, int colLast, bool collapsed)
+{
+	Q_D(Worksheet);
+
+	d->splitColsInfo(colFirst, colLast);
+
+	QList<int> nodes;
+	nodes.append(colFirst);
+	for (int col = colFirst; col <= colLast; ++col) {
+        auto it = d->colsInfo.constFind(col);
+        if (it != d->colsInfo.constEnd()) {
+			if (nodes.last() != col)
+				nodes.append(col);
+            int nextCol = (*it)->lastColumn + 1;
+			if (nextCol <= colLast)
+				nodes.append(nextCol);
+		}
+	}
+
+    for (int idx = 0; idx < nodes.size(); ++idx)
+    {
+		int colStart = nodes[idx];
+        auto it = d->colsInfo.constFind(colStart);
+        if (it != d->colsInfo.constEnd())
+        {
+            (*it)->outlineLevel += 1;
+			if (collapsed)
+                (*it)->hidden = true;
+        }
+        else
+        {
+			int colEnd = (idx == nodes.size() - 1) ? colLast : nodes[idx+1] - 1;
+            QSharedPointer<XlsxColumnInfo> info(new XlsxColumnInfo(colStart, colEnd, false));
+			info->outlineLevel += 1;
+			d->colsInfo.insert(colFirst, info);
+			if (collapsed)
+				info->hidden = true;
+			for (int c = colStart; c <= colEnd; ++c)
+				d->colsInfoHelper[c] = info;
+		}
+	}
+
+	if (collapsed) {
+		int col = colLast+1;
+		d->splitColsInfo(col, col);
+        auto it = d->colsInfo.constFind(col);
+        if (it != d->colsInfo.constEnd())
+            (*it)->collapsed = true;
+		else {
+            QSharedPointer<XlsxColumnInfo> info(new XlsxColumnInfo(col, col, false));
+			info->collapsed = true;
+			d->colsInfo.insert(col, info);
+			d->colsInfoHelper[col] = info;
+		}
+	}
+
+	return false;
+}
+
+/*!
+	Return the range that contains cell data.
+ */
+CellRange Worksheet::dimension() const
+{
+	Q_D(const Worksheet);
+	return d->dimension;
+}
+
+/*
+ Convert the height of a cell from user's units to pixels. If the
+ height hasn't been set by the user we use the default value. If
+ the row is hidden it has a value of zero.
+*/
+int WorksheetPrivate::rowPixelsSize(int row) const
+{
+	double height;
+    auto it = row_sizes.constFind(row);
+    if (it != row_sizes.constEnd())
+        height = it.value();
+	else
+		height = default_row_height;
+	return static_cast<int>(4.0 / 3.0 *height);
+}
+
+/*
+ Convert the width of a cell from user's units to pixels. Excel rounds
+ the column width to the nearest pixel. If the width hasn't been set
+ by the user we use the default value. If the column is hidden it
+ has a value of zero.
+*/
+int WorksheetPrivate::colPixelsSize(int col) const
+{
+	double max_digit_width = 7.0; //For Calabri 11
+	double padding = 5.0;
+	int pixels = 0;
+
+    auto it = col_sizes.constFind(col);
+    if (it != col_sizes.constEnd()) {
+        double width = it.value();
+		if (width < 1)
+			pixels = static_cast<int>(width * (max_digit_width + padding) + 0.5);
+		else
+			pixels = static_cast<int>(width * max_digit_width + 0.5) + padding;
+	} else {
+		pixels = 64;
+	}
+	return pixels;
+}
+
+void WorksheetPrivate::loadXmlSheetData(QXmlStreamReader &reader)
+{
+	Q_Q(Worksheet);
+
+	Q_ASSERT(reader.name() == QLatin1String("sheetData"));
+
+	while (!reader.atEnd() && !(reader.name() == QLatin1String("sheetData") && reader.tokenType() == QXmlStreamReader::EndElement))
+	{
+		if (reader.readNextStartElement())
+		{
+			if (reader.name() == QLatin1String("row"))
+			{
+				QXmlStreamAttributes attributes = reader.attributes();
+
+				if (attributes.hasAttribute(QLatin1String("customFormat"))
+						|| attributes.hasAttribute(QLatin1String("customHeight"))
+						|| attributes.hasAttribute(QLatin1String("hidden"))
+						|| attributes.hasAttribute(QLatin1String("outlineLevel"))
+						|| attributes.hasAttribute(QLatin1String("collapsed")))
+				{
+
+					QSharedPointer<XlsxRowInfo> info(new XlsxRowInfo);
+                    if (attributes.hasAttribute(QLatin1String("customFormat")) &&
+                            attributes.hasAttribute(QLatin1String("s")))
+                    {
+						int idx = attributes.value(QLatin1String("s")).toInt();
+						info->format = workbook->styles()->xfFormat(idx);
+					}
+
+                    if (attributes.hasAttribute(QLatin1String("customHeight")))
+                    {
+						info->customHeight = attributes.value(QLatin1String("customHeight")) == QLatin1String("1");
+						//Row height is only specified when customHeight is set
+                        if(attributes.hasAttribute(QLatin1String("ht")))
+                        {
+							info->height = attributes.value(QLatin1String("ht")).toDouble();
+						}
+					}
+
+					//both "hidden" and "collapsed" default are false
+					info->hidden = attributes.value(QLatin1String("hidden")) == QLatin1String("1");
+					info->collapsed = attributes.value(QLatin1String("collapsed")) == QLatin1String("1");
+
+					if (attributes.hasAttribute(QLatin1String("outlineLevel")))
+						info->outlineLevel = attributes.value(QLatin1String("outlineLevel")).toInt();
+
+					//"r" is optional too.
+                    if (attributes.hasAttribute(QLatin1String("r")))
+                    {
+						int row = attributes.value(QLatin1String("r")).toInt();
+						rowsInfo[row] = info;
+					}
+				}
+
+			}
+			else if (reader.name() == QLatin1String("c")) // Cell
+			{
+
+				//Cell
+				QXmlStreamAttributes attributes = reader.attributes();
+				QString r = attributes.value(QLatin1String("r")).toString();
+				CellReference pos(r);
+
+				//get format
+				Format format;
+				qint32 styleIndex = -1;
+				if (attributes.hasAttribute(QLatin1String("s"))) // Style (defined in the styles.xml file)
+				{
+					//"s" == style index
+					int idx = attributes.value(QLatin1String("s")).toInt();
+					format = workbook->styles()->xfFormat(idx);
+					styleIndex = idx;
+				}
+
+                // Cell::CellType cellType = Cell::NumberType;
+                Cell::CellType cellType = Cell::CustomType;
+
+				if (attributes.hasAttribute(QLatin1String("t"))) // Type
+				{
+					const auto typeString = attributes.value(QLatin1String("t"));
+                    if (typeString == QLatin1String("s")) // Shared string
+					{
+						cellType = Cell::SharedStringType;
+					}
+                    else if (typeString == QLatin1String("inlineStr")) //  Inline String
+					{
+						cellType = Cell::InlineStringType;
+					}
+                    else if (typeString == QLatin1String("str")) // String
+					{
+						cellType = Cell::StringType;
+					}
+                    else if (typeString == QLatin1String("b")) // Boolean
+					{
+						cellType = Cell::BooleanType;
+					}
+                    else if (typeString == QLatin1String("e")) // Error
+					{
+						cellType = Cell::ErrorType;
+					}
+                    else if (typeString == QLatin1String("d")) // Date
+                    {
+                        cellType = Cell::DateType;
+                    }
+                    else if (typeString == QLatin1String("n")) // Number
+                    {
+                        cellType = Cell::NumberType;
+                    }
+					else
+					{
+                        // custom type
+                        cellType = Cell::CustomType;
+					}
+				}
+
+				if (Cell::isDateType(cellType, format))
+				{
+					cellType = Cell::DateType;
+				}
+
+				// create a heap of new cell
+                auto cell = std::make_shared<Cell>(QVariant{}, cellType, format, q, styleIndex);
+
+                while (!reader.atEnd() &&
+                       !(reader.name() == QLatin1String("c") &&
+                         reader.tokenType() == QXmlStreamReader::EndElement))
+				{
+					if (reader.readNextStartElement())
+					{
+                        if (reader.name() == QLatin1String("f")) // formula
+						{
+							CellFormula &formula = cell->d_func()->formula;
+							formula.loadFromXml(reader);
+                            if (formula.formulaType() == CellFormula::SharedType &&
+                                    !formula.formulaText().isEmpty())
+							{
+                                int si = formula.sharedIndex();
+                                sharedFormulaMap[ si ] = formula;
+							}
+						}
+						else if (reader.name() == QLatin1String("v")) // Value
+						{
+							QString value = reader.readElementText();
+							if (cellType == Cell::SharedStringType)
+							{
+								int sst_idx = value.toInt();
+								sharedStrings()->incRefByStringIndex(sst_idx);
+								RichString rs = sharedStrings()->getSharedString(sst_idx);
+								QString strPlainString = rs.toPlainString();
+								cell->d_func()->value = strPlainString;
+								if (rs.isRichString())
+									cell->d_func()->richString = rs;
+							}
+							else if (cellType == Cell::NumberType)
+							{
+								cell->d_func()->value = value.toDouble();
+							}
+							else if (cellType == Cell::BooleanType)
+							{
+								cell->d_func()->value = value.toInt() ? true : false;
+							}
+                            else  if (cellType == Cell::DateType)
+                            {
+                                // [dev54] DateType
+
+                                double dValue = value.toDouble(); // days from 1900(or 1904)
+                                bool bIsDate1904 = q->workbook()->isDate1904();
+
+                                QVariant vDatetimeValue = datetimeFromNumber( dValue, bIsDate1904 );
+                                Q_UNUSED(vDatetimeValue);
+                                // cell->d_func()->value = vDatetimeValue;
+                                cell->d_func()->value = dValue; // dev67
+                            }
+							else
+                            {
+                                // ELSE type
+								cell->d_func()->value = value;
+							}
+
+                        }
+                        else if (reader.name() == QLatin1String("is"))
+                        {
+                            while (!reader.atEnd() &&
+                                   !(reader.name() == QLatin1String("is") &&
+                                   reader.tokenType() == QXmlStreamReader::EndElement))
+                            {
+                                if (reader.readNextStartElement())
+                                {
+									//:Todo, add rich text read support
+                                    if (reader.name() == QLatin1String("t"))
+                                    {
+										cell->d_func()->value = reader.readElementText();
+									}
+								}
+							}
+                        }
+                        else if (reader.name() == QLatin1String("extLst"))
+                        {
+							//skip extLst element
+                            while ( !reader.atEnd() &&
+                                    !(reader.name() == QLatin1String("extLst") &&
+                                    reader.tokenType() == QXmlStreamReader::EndElement))
+                            {
+								reader.readNextStartElement();
+							}
+						}
+					}
+				}
+
+                cellTable[ pos.row() ][ pos.column() ] = cell;
+
+			}
+		}
+	}
+}
+
+void WorksheetPrivate::loadXmlColumnsInfo(QXmlStreamReader &reader)
+{
+	Q_ASSERT(reader.name() == QLatin1String("cols"));
+
+    while (!reader.atEnd() &&
+           !(reader.name() == QLatin1String("cols") &&
+             reader.tokenType() == QXmlStreamReader::EndElement))
+    {
+		reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            if (reader.name() == QLatin1String("col"))
+            {
+                QSharedPointer<XlsxColumnInfo> info(new XlsxColumnInfo(0, 1, false));
+
+				QXmlStreamAttributes colAttrs = reader.attributes();
+				int min = colAttrs.value(QLatin1String("min")).toInt();
+				int max = colAttrs.value(QLatin1String("max")).toInt();
+				info->firstColumn = min;
+				info->lastColumn = max;
+
+				//Flag indicating that the column width for the affected column(s) is different from the
+				// default or has been manually set
+                if(colAttrs.hasAttribute(QLatin1String("customWidth")))
+                {
+					info->customWidth = colAttrs.value(QLatin1String("customWidth")) == QLatin1String("1");
+				}
+
+				//Note, node may have "width" without "customWidth"
+                // [dev54]
+                if (colAttrs.hasAttribute(QLatin1String("width")))
+                {
+					double width = colAttrs.value(QLatin1String("width")).toDouble();
+					info->width = width;
+                    info->isSetWidth = true; // [dev54]
+				}
+
+				info->hidden = colAttrs.value(QLatin1String("hidden")) == QLatin1String("1");
+				info->collapsed = colAttrs.value(QLatin1String("collapsed")) == QLatin1String("1");
+
+                if (colAttrs.hasAttribute(QLatin1String("style")))
+                {
+					int idx = colAttrs.value(QLatin1String("style")).toInt();
+					info->format = workbook->styles()->xfFormat(idx);
+				}
+
+				if (colAttrs.hasAttribute(QLatin1String("outlineLevel")))
+                {
+					info->outlineLevel = colAttrs.value(QLatin1String("outlineLevel")).toInt();
+                }
+
+                // qDebug() << "[debug] " << __FUNCTION__ << min << max << info->width << hasWidth;
+
+				colsInfo.insert(min, info);
+                for (int col = min ; col <= max ; ++col)
+                {
+					colsInfoHelper[col] = info;
+                }
+			}
+		}
+	}
+}
+
+void WorksheetPrivate::loadXmlMergeCells(QXmlStreamReader &reader)
+{
+    // issue #173 https://github.com/QtExcel/QXlsx/issues/173
+
+    Q_ASSERT(reader.name() == QLatin1String("mergeCells"));
+
+    QXmlStreamAttributes attributes = reader.attributes();
+
+    bool isCount = attributes.hasAttribute(QLatin1String("count"));
+    int count = 0;
+    if ( !isCount )
+    {
+        qWarning("no count");
+    }
+    else
+    {
+        count = attributes.value(QLatin1String("count")).toInt();
+    }
+
+    while ( !reader.atEnd() &&
+            !(reader.name() == QLatin1String("mergeCells") &&
+            reader.tokenType() == QXmlStreamReader::EndElement) )
+    {
+        reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            if (reader.name() == QLatin1String("mergeCell"))
+            {
+                QXmlStreamAttributes attrs = reader.attributes();
+                QString rangeStr = attrs.value(QLatin1String("ref")).toString();
+                merges.append(CellRange(rangeStr));
+            }
+        }
+    }
+
+    if (isCount)
+    {
+        int mergesSize = merges.size();
+        if ( mergesSize != count )
+        {
+            qWarning("read merge cells error");
+        }
+    }
+
+}
+
+void WorksheetPrivate::loadXmlDataValidations(QXmlStreamReader &reader)
+{
+	Q_ASSERT(reader.name() == QLatin1String("dataValidations"));
+	QXmlStreamAttributes attributes = reader.attributes();
+	int count = attributes.value(QLatin1String("count")).toInt();
+
+	while (!reader.atEnd() && !(reader.name() == QLatin1String("dataValidations")
+			&& reader.tokenType() == QXmlStreamReader::EndElement)) {
+		reader.readNextStartElement();
+		if (reader.tokenType() == QXmlStreamReader::StartElement
+				&& reader.name() == QLatin1String("dataValidation")) {
+			dataValidationsList.append(DataValidation::loadFromXml(reader));
+		}
+	}
+
+	if (dataValidationsList.size() != count)
+		qDebug("read data validation error");
+}
+
+void WorksheetPrivate::loadXmlSheetViews(QXmlStreamReader &reader)
+{
+	Q_ASSERT(reader.name() == QLatin1String("sheetViews"));
+
+	while (!reader.atEnd() && !(reader.name() == QLatin1String("sheetViews")
+			&& reader.tokenType() == QXmlStreamReader::EndElement)) {
+		reader.readNextStartElement();
+		if (reader.tokenType() == QXmlStreamReader::StartElement && reader.name() == QLatin1String("sheetView")) {
+			QXmlStreamAttributes attrs = reader.attributes();
+			//default false
+			windowProtection = attrs.value(QLatin1String("windowProtection")) == QLatin1String("1");
+			showFormulas = attrs.value(QLatin1String("showFormulas")) == QLatin1String("1");
+			rightToLeft = attrs.value(QLatin1String("rightToLeft")) == QLatin1String("1");
+			tabSelected = attrs.value(QLatin1String("tabSelected")) == QLatin1String("1");
+			//default true
+			showGridLines = attrs.value(QLatin1String("showGridLines")) != QLatin1String("0");
+			showRowColHeaders = attrs.value(QLatin1String("showRowColHeaders")) != QLatin1String("0");
+			showZeros = attrs.value(QLatin1String("showZeros")) != QLatin1String("0");
+			showRuler = attrs.value(QLatin1String("showRuler")) != QLatin1String("0");
+			showOutlineSymbols = attrs.value(QLatin1String("showOutlineSymbols")) != QLatin1String("0");
+			showWhiteSpace = attrs.value(QLatin1String("showWhiteSpace")) != QLatin1String("0");
+		}
+	}
+}
+
+void WorksheetPrivate::loadXmlSheetFormatProps(QXmlStreamReader &reader)
+{
+	Q_ASSERT(reader.name() == QLatin1String("sheetFormatPr"));
+
+    const QXmlStreamAttributes attributes = reader.attributes();
+	XlsxSheetFormatProps formatProps;
+    bool isSetWidth = false;
+
+    // Retain default values
+    for  (const QXmlStreamAttribute &attrib : attributes)
+    {
+        if(attrib.name() == QLatin1String("baseColWidth") )
+        {
+			formatProps.baseColWidth = attrib.value().toInt();
+        }
+        else if(attrib.name() == QLatin1String("customHeight"))
+        {
+			formatProps.customHeight = attrib.value() == QLatin1String("1");
+        }
+        else if(attrib.name() == QLatin1String("defaultColWidth"))
+        {
+            double dDefaultColWidth = attrib.value().toDouble();
+            formatProps.defaultColWidth = dDefaultColWidth;
+            isSetWidth = true;
+        }
+        else if(attrib.name() == QLatin1String("defaultRowHeight"))
+        {
+			formatProps.defaultRowHeight = attrib.value().toDouble();
+        }
+        else if(attrib.name() == QLatin1String("outlineLevelCol"))
+        {
+			formatProps.outlineLevelCol = attrib.value().toInt();
+        }
+        else if(attrib.name() == QLatin1String("outlineLevelRow"))
+        {
+			formatProps.outlineLevelRow = attrib.value().toInt();
+        }
+        else if(attrib.name() == QLatin1String("thickBottom"))
+        {
+			formatProps.thickBottom = attrib.value() == QLatin1String("1");
+        }
+        else if(attrib.name() == QLatin1String("thickTop"))
+        {
+			formatProps.thickTop  = attrib.value() == QLatin1String("1");
+        }
+        else if(attrib.name() == QLatin1String("zeroHeight"))
+        {
+			formatProps.zeroHeight = attrib.value() == QLatin1String("1");
+		}
+	}
+
+    // if (formatProps.defaultColWidth == 0.0)
+    if ( !isSetWidth )
+    {
+        //not set
+        double dCalcWidth = WorksheetPrivate::calculateColWidth(formatProps.baseColWidth);
+        formatProps.defaultColWidth = dCalcWidth;
+	}
+
+    // [dev54]
+    // Where is code of setting 'formatProps'?
+    this->sheetFormatProps = formatProps;
+
+}
+double WorksheetPrivate::calculateColWidth(int characters)
+{
+    // //!Todo
+	//Take normal style' font maximum width and add padding and margin pixels
+    // return characters + 0.5;
+    return characters;
+}
+
+void WorksheetPrivate::loadXmlHyperlinks(QXmlStreamReader &reader)
+{
+	Q_ASSERT(reader.name() == QLatin1String("hyperlinks"));
+
+	while (!reader.atEnd() && !(reader.name() == QLatin1String("hyperlinks")
+			&& reader.tokenType() == QXmlStreamReader::EndElement)) {
+		reader.readNextStartElement();
+		if (reader.tokenType() == QXmlStreamReader::StartElement && reader.name() == QLatin1String("hyperlink")) {
+			QXmlStreamAttributes attrs = reader.attributes();
+			CellReference pos(attrs.value(QLatin1String("ref")).toString());
+			if (pos.isValid()) { //Valid
+				QSharedPointer<XlsxHyperlinkData> link(new XlsxHyperlinkData);
+				link->display = attrs.value(QLatin1String("display")).toString();
+				link->tooltip = attrs.value(QLatin1String("tooltip")).toString();
+				link->location = attrs.value(QLatin1String("location")).toString();
+
+				if (attrs.hasAttribute(QLatin1String("r:id"))) {
+					link->linkType = XlsxHyperlinkData::External;
+					XlsxRelationship ship = relationships->getRelationshipById(attrs.value(QLatin1String("r:id")).toString());
+					link->target = ship.target;
+				} else {
+					link->linkType = XlsxHyperlinkData::Internal;
+				}
+
+				urlTable[pos.row()][pos.column()] = link;
+			}
+		}
+	}
+}
+
+QList <QSharedPointer<XlsxColumnInfo> > WorksheetPrivate::getColumnInfoList(int colFirst, int colLast)
+{
+	QList <QSharedPointer<XlsxColumnInfo> > columnsInfoList;
+    if (isColumnRangeValid(colFirst,colLast))
+	{
+		QList<int> nodes = getColumnIndexes(colFirst, colLast);
+
+        for (int idx = 0; idx < nodes.size(); ++idx)
+        {
+			int colStart = nodes[idx];
+            auto it = colsInfo.constFind(colStart);
+            if (it != colsInfo.constEnd())
+            {
+                columnsInfoList.append(*it);
+            }
+            else
+            {
+				int colEnd = (idx == nodes.size() - 1) ? colLast : nodes[idx+1] - 1;
+                QSharedPointer<XlsxColumnInfo> info(new XlsxColumnInfo(colStart, colEnd, false));
+				colsInfo.insert(colFirst, info);
+				columnsInfoList.append(info);
+				for (int c = colStart; c <= colEnd; ++c)
+                {
+					colsInfoHelper[c] = info;
+                }
+			}
+		}
+	}
+
+	return columnsInfoList;
+}
+
+QList <QSharedPointer<XlsxRowInfo> > WorksheetPrivate::getRowInfoList(int rowFirst, int rowLast)
+{
+	QList <QSharedPointer<XlsxRowInfo> > rowInfoList;
+
+	int min_col = dimension.firstColumn() < 1 ? 1 : dimension.firstColumn();
+
+	for(int row = rowFirst; row <= rowLast; ++row) {
+		if (checkDimensions(row, min_col, false, true))
+			continue;
+
+		QSharedPointer<XlsxRowInfo> rowInfo;
+		if ((rowsInfo[row]).isNull()){
+			rowsInfo[row] = QSharedPointer<XlsxRowInfo>(new XlsxRowInfo());
+		}
+		rowInfoList.append(rowsInfo[row]);
+	}
+
+	return rowInfoList;
+}
+
+bool Worksheet::loadFromXmlFile(QIODevice *device)
+{
+	Q_D(Worksheet);
+
+	QXmlStreamReader reader(device);
+    while (!reader.atEnd())
+    {
+		reader.readNextStartElement();
+        if (reader.tokenType() == QXmlStreamReader::StartElement)
+        {
+            if (reader.name() == QLatin1String("dimension"))
+            {
+				QXmlStreamAttributes attributes = reader.attributes();
+				QString range = attributes.value(QLatin1String("ref")).toString();
+				d->dimension = CellRange(range);
+            }
+            else if (reader.name() == QLatin1String("sheetViews"))
+            {
+				d->loadXmlSheetViews(reader);
+            }
+            else if (reader.name() == QLatin1String("sheetFormatPr"))
+            {
+				d->loadXmlSheetFormatProps(reader);
+            }
+            else if (reader.name() == QLatin1String("cols"))
+            {
+				d->loadXmlColumnsInfo(reader);
+            }
+            else if (reader.name() == QLatin1String("sheetData"))
+            {
+				d->loadXmlSheetData(reader);
+            }
+            else if (reader.name() == QLatin1String("mergeCells"))
+            {
+				d->loadXmlMergeCells(reader);
+            }
+            else if (reader.name() == QLatin1String("dataValidations"))
+            {
+				d->loadXmlDataValidations(reader);
+            }
+            else if (reader.name() == QLatin1String("conditionalFormatting"))
+            {
+				ConditionalFormatting cf;
+				cf.loadFromXml(reader, workbook()->styles());
+				d->conditionalFormattingList.append(cf);
+            }
+            else if (reader.name() == QLatin1String("hyperlinks"))
+            {
+				d->loadXmlHyperlinks(reader);
+            }
+            else if(reader.name() == QLatin1String("pageSetup"))
+            {
+                QXmlStreamAttributes attributes = reader.attributes();
+
+                d->PpaperSize = attributes.value(QLatin1String("paperSize")).toString().trimmed();
+                d->Pscale = attributes.value(QLatin1String("scale")).toString().trimmed();
+                d->PfirstPageNumber = attributes.value(QLatin1String("firstPageNumber")).toString().trimmed();
+                d->Porientation = attributes.value(QLatin1String("orientation")).toString().trimmed();
+                d->PuseFirstPageNumber = attributes.value(QLatin1String("useFirstPageNumber")).toString().trimmed();
+                d->PhorizontalDpi = attributes.value(QLatin1String("horizontalDpi")).toString().trimmed();
+                d->PverticalDpi = attributes.value(QLatin1String("verticalDpi")).toString().trimmed();
+                d->Prid = attributes.value(QLatin1String("r:id")).toString().trimmed();
+                d->Pcopies = attributes.value(QLatin1String("copies")).toString().trimmed();
+            }
+            else if(reader.name() == QLatin1String("pageMargins"))
+            {
+                QXmlStreamAttributes attributes = reader.attributes();
+
+                d->PMfooter= attributes.value(QLatin1String("footer")).toString().trimmed();
+                d->PMheader = attributes.value(QLatin1String("header")).toString().trimmed();
+                d->PMbotton = attributes.value(QLatin1String("bottom")).toString().trimmed();
+                d->PMtop = attributes.value(QLatin1String("top")).toString().trimmed();
+                d->PMright = attributes.value(QLatin1String("right")).toString().trimmed();
+                d->PMleft = attributes.value(QLatin1String("left")).toString().trimmed();
+            }
+            else if(reader.name() == QLatin1String("headerFooter"))
+            {
+                // dev40
+                while (reader.readNextStartElement())
+                {
+                    if (reader.name() == QLatin1String("oddHeader"))
+                        d->ModdHeader = reader.readElementText();
+
+                    if (reader.name() == QLatin1String("oddFooter"))
+                            d->MoodFooter = reader.readElementText();
+                }
+            }
+            else 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);
+            }
+            else if (reader.name() == QLatin1String("extLst"))
+            {
+				//Todo: add extLst support
+                while ( !reader.atEnd() &&
+                        !(reader.name() == QLatin1String("extLst") &&
+                          reader.tokenType() == QXmlStreamReader::EndElement))
+                {
+					reader.readNextStartElement();
+				}
+			}
+		}
+	}
+
+	d->validateDimension();
+	return true;
+}
+
+/*
+ *  Documents imported from Google Docs does not contain dimension data.
+ */
+void WorksheetPrivate::validateDimension()
+{
+	if (dimension.isValid() || cellTable.isEmpty())
+		return;
+
+	const auto firstRow = cellTable.constBegin().key();
+
+    const auto lastRow = (--cellTable.constEnd()).key();
+
+	int firstColumn = -1;
+	int lastColumn = -1;
+
+    for ( auto&& it = cellTable.constBegin()
+            ; it != cellTable.constEnd()
+            ; ++it )
+    {
+        Q_ASSERT(!it.value().isEmpty());
+
+        if (firstColumn == -1 || it.value().constBegin().key() < firstColumn)
+            firstColumn = it.value().constBegin().key();
+
+        if (lastColumn == -1 || (--it.value().constEnd()).key() > lastColumn)
+        {
+            lastColumn = (--it.value().constEnd()).key();
+        }
+    }
+
+	CellRange cr(firstRow, firstColumn, lastRow, lastColumn);
+
+	if (cr.isValid())
+		dimension = cr;
+}
+
+/*!
+ * \internal
+ *  Unit test can use this member to get sharedString object.
+ */
+SharedStrings *WorksheetPrivate::sharedStrings() const
+{
+	return workbook->sharedStrings();
+}
+
+QVector<CellLocation> Worksheet::getFullCells(int* maxRow, int* maxCol)
+{
+    Q_D(const Worksheet);
+
+    // return values
+    (*maxRow) = -1;
+    (*maxCol) = -1;
+    QVector<CellLocation> ret;
+
+    // QString privateName = d->name; // name of sheet (not object type)
+    // qDebug() << privateName ;
+
+    if ( d->type == AbstractSheet::ST_WorkSheet  )
+    {
+        // use current sheet
+    }
+    else if ( d->type == AbstractSheet::ST_ChartSheet )
+    {
+        return ret;
+    }
+    else
+    {
+        qWarning("unsupported sheet type.");
+        Q_ASSERT(false);
+        return ret;
+    }
+
+    QMapIterator< int, QMap< int, std::shared_ptr<Cell> > > _it( d->cellTable );
+
+    while ( _it.hasNext() )
+    {
+        _it.next();
+
+        int keyI = _it.key(); // key (cell row)
+        QMapIterator<int, std::shared_ptr<Cell> > _iit( _it.value() ); // value
+
+        while ( _iit.hasNext() )
+        {
+            _iit.next();
+
+            int keyII = _iit.key(); // key (cell column)
+            std::shared_ptr<Cell> ptrCell = _iit.value(); // value
+
+            CellLocation cl;
+
+            cl.row = keyI;
+            if ( keyI > (*maxRow) )
+            {
+                (*maxRow) = keyI;
+            }
+
+            cl.col = keyII;
+            if ( keyII > (*maxCol) )
+            {
+                (*maxCol) = keyII;
+            }
+
+            cl.cell = ptrCell;
+
+            ret.push_back( cl );
+        }
+    }
+
+    return ret;
+}
+
+QT_END_NAMESPACE_XLSX
diff --git a/internal_system_v1/QXlsx/source/xlsxzipreader.cpp b/internal_system_v1/QXlsx/source/xlsxzipreader.cpp
new file mode 100644
index 0000000..6710a3b
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxzipreader.cpp
@@ -0,0 +1,50 @@
+// 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
diff --git a/internal_system_v1/QXlsx/source/xlsxzipwriter.cpp b/internal_system_v1/QXlsx/source/xlsxzipwriter.cpp
new file mode 100644
index 0000000..63f91c3
--- /dev/null
+++ b/internal_system_v1/QXlsx/source/xlsxzipwriter.cpp
@@ -0,0 +1,48 @@
+// xlsxzipwriter.cpp
+
+#include "xlsxzipwriter_p.h"
+
+#include <QtGlobal>
+#include <QDebug>
+#include <private/qzipwriter_p.h>
+
+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
diff --git a/internal_system_v1/auditproject.ui b/internal_system_v1/auditproject.ui
index abe6655..f563d9a 100644
--- a/internal_system_v1/auditproject.ui
+++ b/internal_system_v1/auditproject.ui
@@ -14,253 +14,243 @@
    <string>MainWindow</string>
   </property>
   <widget class="QWidget" name="centralwidget">
-   <widget class="QLabel" name="label">
-    <property name="geometry">
-     <rect>
-      <x>80</x>
-      <y>40</y>
-      <width>481</width>
-      <height>71</height>
-     </rect>
-    </property>
-    <property name="text">
-     <string>瀹¤椤圭洰</string>
-    </property>
-   </widget>
-   <widget class="QTableWidget" name="tableWidget">
-    <property name="geometry">
-     <rect>
-      <x>50</x>
-      <y>110</y>
-      <width>711</width>
-      <height>431</height>
-     </rect>
-    </property>
-    <attribute name="verticalHeaderVisible">
-     <bool>false</bool>
-    </attribute>
-    <row>
-     <property name="text">
-      <string>1</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <column>
-     <property name="text">
-      <string>鎸囨爣鍚嶇О</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>浠g爜</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>缁熻(鍗曚綅锛氫釜)</string>
-     </property>
-    </column>
+   <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="0">
-     <property name="text">
-      <string>瀹¤椤圭洰</string>
-     </property>
-     <property name="font">
-      <font>
-       <weight>75</weight>
-       <bold>true</bold>
-      </font>
-     </property>
-    </item>
-    <item row="0" column="1">
-     <property name="text">
-      <string>020100</string>
-     </property>
-    </item>
-    <item row="0" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
+     <widget class="QLabel" name="label">
+      <property name="text">
+       <string>瀹¤椤圭洰</string>
+      </property>
+     </widget>
     </item>
     <item row="1" column="0">
-     <property name="text">
-      <string>璐交钀藉疄鍥藉閲嶅ぇ鏀跨瓥鎺柦瀹¤</string>
-     </property>
+     <widget class="QTableWidget" name="tableWidget">
+      <attribute name="verticalHeaderVisible">
+       <bool>false</bool>
+      </attribute>
+      <row>
+       <property name="text">
+        <string>1</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <column>
+       <property name="text">
+        <string>鎸囨爣鍚嶇О</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>浠g爜</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>缁熻(鍗曚綅锛氫釜)</string>
+       </property>
+      </column>
+      <item row="0" column="0">
+       <property name="text">
+        <string>瀹¤椤圭洰</string>
+       </property>
+       <property name="font">
+        <font>
+         <weight>75</weight>
+         <bold>true</bold>
+        </font>
+       </property>
+      </item>
+      <item row="0" column="1">
+       <property name="text">
+        <string>020100</string>
+       </property>
+      </item>
+      <item row="0" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="1" column="0">
+       <property name="text">
+        <string>璐交钀藉疄鍥藉閲嶅ぇ鏀跨瓥鎺柦瀹¤</string>
+       </property>
+      </item>
+      <item row="1" column="1">
+       <property name="text">
+        <string>020101</string>
+       </property>
+      </item>
+      <item row="1" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="2" column="0">
+       <property name="text">
+        <string>璐㈡斂璐㈠姟鏀舵敮瀹¤</string>
+       </property>
+      </item>
+      <item row="2" column="1">
+       <property name="text">
+        <string>020102</string>
+       </property>
+      </item>
+      <item row="2" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="3" column="0">
+       <property name="text">
+        <string>鍥哄畾璧勪骇鎶曡祫瀹¤</string>
+       </property>
+      </item>
+      <item row="3" column="1">
+       <property name="text">
+        <string>020103</string>
+       </property>
+      </item>
+      <item row="3" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="4" column="0">
+       <property name="text">
+        <string>鍐呴儴鎺у埗鍜岄闄╃鐞嗗璁�</string>
+       </property>
+      </item>
+      <item row="4" column="1">
+       <property name="text">
+        <string>020104</string>
+       </property>
+      </item>
+      <item row="4" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="5" column="0">
+       <property name="text">
+        <string>缁忔祹璐d换瀹¤</string>
+       </property>
+      </item>
+      <item row="5" column="1">
+       <property name="text">
+        <string>020105</string>
+       </property>
+      </item>
+      <item row="5" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="6" column="0">
+       <property name="text">
+        <string>淇℃伅绯荤粺瀹¤</string>
+       </property>
+      </item>
+      <item row="6" column="1">
+       <property name="text">
+        <string>020106</string>
+       </property>
+      </item>
+      <item row="6" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="7" column="0">
+       <property name="text">
+        <string>澧冨瀹¤</string>
+       </property>
+      </item>
+      <item row="7" column="1">
+       <property name="text">
+        <string>020107</string>
+       </property>
+      </item>
+      <item row="7" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="8" column="0">
+       <property name="text">
+        <string>鍏朵粬</string>
+       </property>
+      </item>
+      <item row="8" column="1">
+       <property name="text">
+        <string>020108</string>
+       </property>
+      </item>
+      <item row="8" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="9" column="0">
+       <property name="text">
+        <string>濮旀墭澶栧寘椤圭洰</string>
+       </property>
+      </item>
+      <item row="9" column="1">
+       <property name="text">
+        <string>020111</string>
+       </property>
+      </item>
+      <item row="9" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+     </widget>
     </item>
-    <item row="1" column="1">
-     <property name="text">
-      <string>020101</string>
-     </property>
-    </item>
-    <item row="1" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="2" column="0">
-     <property name="text">
-      <string>璐㈡斂璐㈠姟鏀舵敮瀹¤</string>
-     </property>
-    </item>
-    <item row="2" column="1">
-     <property name="text">
-      <string>020102</string>
-     </property>
-    </item>
-    <item row="2" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="3" column="0">
-     <property name="text">
-      <string>鍥哄畾璧勪骇鎶曡祫瀹¤</string>
-     </property>
-    </item>
-    <item row="3" column="1">
-     <property name="text">
-      <string>020103</string>
-     </property>
-    </item>
-    <item row="3" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="4" column="0">
-     <property name="text">
-      <string>鍐呴儴鎺у埗鍜岄闄╃鐞嗗璁�</string>
-     </property>
-    </item>
-    <item row="4" column="1">
-     <property name="text">
-      <string>020104</string>
-     </property>
-    </item>
-    <item row="4" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="5" column="0">
-     <property name="text">
-      <string>缁忔祹璐d换瀹¤</string>
-     </property>
-    </item>
-    <item row="5" column="1">
-     <property name="text">
-      <string>020105</string>
-     </property>
-    </item>
-    <item row="5" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="6" column="0">
-     <property name="text">
-      <string>淇℃伅绯荤粺瀹¤</string>
-     </property>
-    </item>
-    <item row="6" column="1">
-     <property name="text">
-      <string>020106</string>
-     </property>
-    </item>
-    <item row="6" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="7" column="0">
-     <property name="text">
-      <string>澧冨瀹¤</string>
-     </property>
-    </item>
-    <item row="7" column="1">
-     <property name="text">
-      <string>020107</string>
-     </property>
-    </item>
-    <item row="7" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="8" column="0">
-     <property name="text">
-      <string>鍏朵粬</string>
-     </property>
-    </item>
-    <item row="8" column="1">
-     <property name="text">
-      <string>020108</string>
-     </property>
-    </item>
-    <item row="8" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="9" column="0">
-     <property name="text">
-      <string>濮旀墭澶栧寘椤圭洰</string>
-     </property>
-    </item>
-    <item row="9" column="1">
-     <property name="text">
-      <string>020111</string>
-     </property>
-    </item>
-    <item row="9" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-   </widget>
+   </layout>
   </widget>
   <widget class="QMenuBar" name="menubar">
    <property name="geometry">
@@ -268,7 +258,7 @@
      <x>0</x>
      <y>0</y>
      <width>800</width>
-     <height>25</height>
+     <height>26</height>
     </rect>
    </property>
   </widget>
diff --git a/internal_system_v1/auditworkload.ui b/internal_system_v1/auditworkload.ui
index f30dcf6..ddcf886 100644
--- a/internal_system_v1/auditworkload.ui
+++ b/internal_system_v1/auditworkload.ui
@@ -14,64 +14,57 @@
    <string>MainWindow</string>
   </property>
   <widget class="QWidget" name="centralwidget">
-   <widget class="QLabel" name="label">
-    <property name="geometry">
-     <rect>
-      <x>110</x>
-      <y>70</y>
-      <width>471</width>
-      <height>61</height>
-     </rect>
-    </property>
-    <property name="text">
-     <string>鍐呭宸ヤ綔閲�</string>
-    </property>
-   </widget>
-   <widget class="QTableWidget" name="tableWidget">
-    <property name="geometry">
-     <rect>
-      <x>30</x>
-      <y>150</y>
-      <width>741</width>
-      <height>351</height>
-     </rect>
-    </property>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <column>
-     <property name="text">
-      <string>鎸囨爣鍚嶇О</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>浠g爜</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>鏁伴噺(浜烘棩)</string>
-     </property>
-    </column>
+   <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="0">
-     <property name="text">
-      <string>鏈~鎶ュ懆鏈熷唴閮ㄥ璁″伐浣滈噺</string>
-     </property>
+     <widget class="QLabel" name="label">
+      <property name="text">
+       <string>鍐呭宸ヤ綔閲�</string>
+      </property>
+     </widget>
     </item>
-    <item row="0" column="1">
-     <property name="text">
-      <string>020200</string>
-     </property>
+    <item row="1" column="0">
+     <widget class="QTableWidget" name="tableWidget">
+      <attribute name="verticalHeaderVisible">
+       <bool>false</bool>
+      </attribute>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <column>
+       <property name="text">
+        <string>鎸囨爣鍚嶇О</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>浠g爜</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>鏁伴噺(浜烘棩)</string>
+       </property>
+      </column>
+      <item row="0" column="0">
+       <property name="text">
+        <string>鏈~鎶ュ懆鏈熷唴閮ㄥ璁″伐浣滈噺</string>
+       </property>
+      </item>
+      <item row="0" column="1">
+       <property name="text">
+        <string>020200</string>
+       </property>
+      </item>
+      <item row="0" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+     </widget>
     </item>
-    <item row="0" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-   </widget>
+   </layout>
   </widget>
   <widget class="QMenuBar" name="menubar">
    <property name="geometry">
diff --git a/internal_system_v1/caseclue.cpp b/internal_system_v1/caseclue.cpp
index ce74a24..5d5017a 100644
--- a/internal_system_v1/caseclue.cpp
+++ b/internal_system_v1/caseclue.cpp
@@ -6,6 +6,7 @@
     ui(new Ui::CaseClue)
 {
     ui->setupUi(this);
+    ui->tableWidget->setColumnWidth(0,300);
 }
 
 CaseClue::~CaseClue()
diff --git a/internal_system_v1/caseclue.ui b/internal_system_v1/caseclue.ui
index 96e37a6..150b86b 100644
--- a/internal_system_v1/caseclue.ui
+++ b/internal_system_v1/caseclue.ui
@@ -14,19 +14,92 @@
    <string>MainWindow</string>
   </property>
   <widget class="QWidget" name="centralwidget">
-   <widget class="QLabel" name="label">
-    <property name="geometry">
-     <rect>
-      <x>160</x>
-      <y>120</y>
-      <width>301</width>
-      <height>101</height>
-     </rect>
-    </property>
-    <property name="text">
-     <string>妗堜欢绾跨储</string>
-    </property>
-   </widget>
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QLabel" name="label">
+      <property name="text">
+       <string>妗堜欢绾跨储</string>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="0">
+     <widget class="QTableWidget" name="tableWidget">
+      <attribute name="verticalHeaderVisible">
+       <bool>false</bool>
+      </attribute>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <column>
+       <property name="text">
+        <string>鎸囨爣鍚嶇О</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>浠g爜</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>璁¢噺鍗曚綅</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>鏁伴噺</string>
+       </property>
+      </column>
+      <item row="0" column="0">
+       <property name="text">
+        <string>鍚戝徃娉曟満鍏崇Щ閫佹垨鎶ュ憡妗堜欢绾跨储</string>
+       </property>
+      </item>
+      <item row="0" column="1">
+       <property name="text">
+        <string>020800</string>
+       </property>
+      </item>
+      <item row="0" column="2">
+       <property name="text">
+        <string>浠�</string>
+       </property>
+      </item>
+      <item row="0" column="3">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="1" column="0">
+       <property name="text">
+        <string>娑夋浜哄憳</string>
+       </property>
+      </item>
+      <item row="1" column="1">
+       <property name="text">
+        <string>020801</string>
+       </property>
+      </item>
+      <item row="1" column="2">
+       <property name="text">
+        <string>浜�</string>
+       </property>
+      </item>
+      <item row="1" column="3">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+     </widget>
+    </item>
+   </layout>
   </widget>
   <widget class="QMenuBar" name="menubar">
    <property name="geometry">
@@ -34,7 +107,7 @@
      <x>0</x>
      <y>0</y>
      <width>800</width>
-     <height>25</height>
+     <height>26</height>
     </rect>
    </property>
   </widget>
diff --git a/internal_system_v1/clientmainwindow.cpp b/internal_system_v1/clientmainwindow.cpp
index ae38526..442b832 100644
--- a/internal_system_v1/clientmainwindow.cpp
+++ b/internal_system_v1/clientmainwindow.cpp
@@ -1,5 +1,6 @@
 #include "clientmainwindow.h"
 #include "ui_clientmainwindow.h"
+#include <QDebug>
 
 ClientMainWindow::ClientMainWindow(QWidget *parent) :
     QMainWindow(parent),
@@ -77,3 +78,20 @@
 {
     ui->stackedWidget->setCurrentIndex(7);
 }
+
+void ClientMainWindow::on_pushButton_clicked()
+{
+    QXlsx::Document doc;
+    doc.write(1,2,"mayibase");
+    doc.write(2,2,"is good");
+    doc.write("A1","鐮佽殎杞欢");
+    doc.mergeCells("A1:A4");
+    doc.mergeCells("B1:C1");
+    if(doc.saveAs("test.xlsx"))
+    {
+        qDebug()<<"save is ok";
+    }else{
+        qDebug()<<"save is fail";
+    }
+
+}
diff --git a/internal_system_v1/clientmainwindow.h b/internal_system_v1/clientmainwindow.h
index 2e9bf0e..6b6b699 100644
--- a/internal_system_v1/clientmainwindow.h
+++ b/internal_system_v1/clientmainwindow.h
@@ -11,6 +11,8 @@
 #include "punish.h"
 #include "caseclue.h"
 
+#include "xlsxdocument.h"
+
 namespace Ui {
 class ClientMainWindow;
 }
@@ -41,6 +43,8 @@
 
     void on_pushButton_caseClue_clicked();
 
+    void on_pushButton_clicked();
+
 private:
     Ui::ClientMainWindow *ui;
     AuditProject *m_auditPro;
diff --git a/internal_system_v1/clientmainwindow.ui b/internal_system_v1/clientmainwindow.ui
index 6aae787..87bdd55 100644
--- a/internal_system_v1/clientmainwindow.ui
+++ b/internal_system_v1/clientmainwindow.ui
@@ -18,7 +18,7 @@
     <item row="0" column="0">
      <widget class="QTabWidget" name="tabWidget">
       <property name="currentIndex">
-       <number>1</number>
+       <number>2</number>
       </property>
       <widget class="QWidget" name="tab">
        <attribute name="title">
@@ -157,6 +157,24 @@
         </item>
        </layout>
       </widget>
+      <widget class="QWidget" name="tab_3">
+       <attribute name="title">
+        <string>QXlsx</string>
+       </attribute>
+       <widget class="QPushButton" name="pushButton">
+        <property name="geometry">
+         <rect>
+          <x>90</x>
+          <y>60</y>
+          <width>191</width>
+          <height>61</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>test</string>
+        </property>
+       </widget>
+      </widget>
      </widget>
     </item>
    </layout>
@@ -167,7 +185,7 @@
      <x>0</x>
      <y>0</y>
      <width>1075</width>
-     <height>25</height>
+     <height>26</height>
     </rect>
    </property>
   </widget>
diff --git a/internal_system_v1/internal_system_v1.pro b/internal_system_v1/internal_system_v1.pro
index aabb6d7..475e598 100644
--- a/internal_system_v1/internal_system_v1.pro
+++ b/internal_system_v1/internal_system_v1.pro
@@ -56,3 +56,5 @@
     problemnotmoney.ui \
     punish.ui \
     caseclue.ui
+
+include(QXlsx/QXlsx.pri)
diff --git a/internal_system_v1/problemcount.ui b/internal_system_v1/problemcount.ui
index beebaa8..15d322e 100644
--- a/internal_system_v1/problemcount.ui
+++ b/internal_system_v1/problemcount.ui
@@ -14,192 +14,182 @@
    <string>MainWindow</string>
   </property>
   <widget class="QWidget" name="centralwidget">
-   <widget class="QLabel" name="label">
-    <property name="geometry">
-     <rect>
-      <x>120</x>
-      <y>20</y>
-      <width>421</width>
-      <height>91</height>
-     </rect>
-    </property>
-    <property name="text">
-     <string>闂涓暟</string>
-    </property>
-   </widget>
-   <widget class="QTableWidget" name="tableWidget">
-    <property name="geometry">
-     <rect>
-      <x>40</x>
-      <y>130</y>
-      <width>741</width>
-      <height>411</height>
-     </rect>
-    </property>
-    <attribute name="verticalHeaderVisible">
-     <bool>false</bool>
-    </attribute>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <column>
-     <property name="text">
-      <string>鎸囨爣鍚嶇О</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>浠g爜</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>鏁伴噺(涓�)</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>涓婁紶浣愯瘉璧勬枡</string>
-     </property>
-    </column>
+   <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="0">
-     <property name="text">
-      <string>瀹¤鍙戠幇闂涓暟</string>
-     </property>
-    </item>
-    <item row="0" column="1">
-     <property name="text">
-      <string>020400</string>
-     </property>
-    </item>
-    <item row="0" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
+     <widget class="QLabel" name="label">
+      <property name="text">
+       <string>闂涓暟</string>
+      </property>
+     </widget>
     </item>
     <item row="1" column="0">
-     <property name="text">
-      <string>閲戦绫婚棶棰樹釜鏁�</string>
-     </property>
+     <widget class="QTableWidget" name="tableWidget">
+      <attribute name="verticalHeaderVisible">
+       <bool>false</bool>
+      </attribute>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <column>
+       <property name="text">
+        <string>鎸囨爣鍚嶇О</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>浠g爜</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>鏁伴噺(涓�)</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>涓婁紶浣愯瘉璧勬枡</string>
+       </property>
+      </column>
+      <item row="0" column="0">
+       <property name="text">
+        <string>瀹¤鍙戠幇闂涓暟</string>
+       </property>
+      </item>
+      <item row="0" column="1">
+       <property name="text">
+        <string>020400</string>
+       </property>
+      </item>
+      <item row="0" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="1" column="0">
+       <property name="text">
+        <string>閲戦绫婚棶棰樹釜鏁�</string>
+       </property>
+      </item>
+      <item row="1" column="1">
+       <property name="text">
+        <string>020410</string>
+       </property>
+      </item>
+      <item row="1" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="2" column="0">
+       <property name="text">
+        <string>闈為噾棰濈被闂涓暟</string>
+       </property>
+      </item>
+      <item row="2" column="1">
+       <property name="text">
+        <string>020420</string>
+       </property>
+      </item>
+      <item row="2" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="3" column="0">
+       <property name="text">
+        <string>鍥藉鏀跨瓥鎺柦钀藉疄鏂归潰</string>
+       </property>
+      </item>
+      <item row="3" column="1">
+       <property name="text">
+        <string>020421</string>
+       </property>
+      </item>
+      <item row="3" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="4" column="0">
+       <property name="text">
+        <string>鍙戝睍瑙勫垝涓庢垬鐣ュ喅绛栨柟闈�</string>
+       </property>
+      </item>
+      <item row="4" column="1">
+       <property name="text">
+        <string>020422</string>
+       </property>
+      </item>
+      <item row="4" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="5" column="0">
+       <property name="text">
+        <string>鍐呴儴鎺у埗涓庨闄╃鐞嗘柟闈�</string>
+       </property>
+      </item>
+      <item row="5" column="1">
+       <property name="text">
+        <string>020423</string>
+       </property>
+      </item>
+      <item row="5" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="6" column="0">
+       <property name="text">
+        <string>鍏朵粬</string>
+       </property>
+      </item>
+      <item row="6" column="1">
+       <property name="text">
+        <string>020424</string>
+       </property>
+      </item>
+      <item row="6" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+     </widget>
     </item>
-    <item row="1" column="1">
-     <property name="text">
-      <string>020410</string>
-     </property>
-    </item>
-    <item row="1" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="2" column="0">
-     <property name="text">
-      <string>闈為噾棰濈被闂涓暟</string>
-     </property>
-    </item>
-    <item row="2" column="1">
-     <property name="text">
-      <string>020420</string>
-     </property>
-    </item>
-    <item row="2" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="3" column="0">
-     <property name="text">
-      <string>鍥藉鏀跨瓥鎺柦钀藉疄鏂归潰</string>
-     </property>
-    </item>
-    <item row="3" column="1">
-     <property name="text">
-      <string>020421</string>
-     </property>
-    </item>
-    <item row="3" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="4" column="0">
-     <property name="text">
-      <string>鍙戝睍瑙勫垝涓庢垬鐣ュ喅绛栨柟闈�</string>
-     </property>
-    </item>
-    <item row="4" column="1">
-     <property name="text">
-      <string>020422</string>
-     </property>
-    </item>
-    <item row="4" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="5" column="0">
-     <property name="text">
-      <string>鍐呴儴鎺у埗涓庨闄╃鐞嗘柟闈�</string>
-     </property>
-    </item>
-    <item row="5" column="1">
-     <property name="text">
-      <string>020423</string>
-     </property>
-    </item>
-    <item row="5" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="6" column="0">
-     <property name="text">
-      <string>鍏朵粬</string>
-     </property>
-    </item>
-    <item row="6" column="1">
-     <property name="text">
-      <string>020424</string>
-     </property>
-    </item>
-    <item row="6" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-   </widget>
+   </layout>
   </widget>
   <widget class="QMenuBar" name="menubar">
    <property name="geometry">
diff --git a/internal_system_v1/problemmoney.ui b/internal_system_v1/problemmoney.ui
index 22cb76b..f1e8445 100644
--- a/internal_system_v1/problemmoney.ui
+++ b/internal_system_v1/problemmoney.ui
@@ -14,272 +14,262 @@
    <string>MainWindow</string>
   </property>
   <widget class="QWidget" name="centralwidget">
-   <widget class="QLabel" name="label">
-    <property name="geometry">
-     <rect>
-      <x>120</x>
-      <y>30</y>
-      <width>371</width>
-      <height>51</height>
-     </rect>
-    </property>
-    <property name="text">
-     <string>闂閲戦</string>
-    </property>
-   </widget>
-   <widget class="QTableWidget" name="tableWidget">
-    <property name="geometry">
-     <rect>
-      <x>30</x>
-      <y>120</y>
-      <width>741</width>
-      <height>421</height>
-     </rect>
-    </property>
-    <attribute name="verticalHeaderVisible">
-     <bool>false</bool>
-    </attribute>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string/>
-     </property>
-    </row>
-    <column>
-     <property name="text">
-      <string>鎸囨爣鍚嶇О</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>浠g爜</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>鏁伴噺(鍏�)</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>涓婁紶浣愯瘉璧勬枡</string>
-     </property>
-    </column>
+   <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="0">
-     <property name="text">
-      <string>瀹¤鍙戠幇闂閲戦</string>
-     </property>
-    </item>
-    <item row="0" column="1">
-     <property name="text">
-      <string>020300</string>
-     </property>
-    </item>
-    <item row="0" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
+     <widget class="QLabel" name="label">
+      <property name="text">
+       <string>闂閲戦</string>
+      </property>
+     </widget>
     </item>
     <item row="1" column="0">
-     <property name="text">
-      <string>缁╂晥绫婚棶棰橀噾棰�</string>
-     </property>
+     <widget class="QTableWidget" name="tableWidget">
+      <attribute name="verticalHeaderVisible">
+       <bool>false</bool>
+      </attribute>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string/>
+       </property>
+      </row>
+      <column>
+       <property name="text">
+        <string>鎸囨爣鍚嶇О</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>浠g爜</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>鏁伴噺(鍏�)</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>涓婁紶浣愯瘉璧勬枡</string>
+       </property>
+      </column>
+      <item row="0" column="0">
+       <property name="text">
+        <string>瀹¤鍙戠幇闂閲戦</string>
+       </property>
+      </item>
+      <item row="0" column="1">
+       <property name="text">
+        <string>020300</string>
+       </property>
+      </item>
+      <item row="0" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="1" column="0">
+       <property name="text">
+        <string>缁╂晥绫婚棶棰橀噾棰�</string>
+       </property>
+      </item>
+      <item row="1" column="1">
+       <property name="text">
+        <string>020310</string>
+       </property>
+      </item>
+      <item row="1" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="2" column="0">
+       <property name="text">
+        <string>鍚堣鎬ч棶棰橀噾棰�</string>
+       </property>
+      </item>
+      <item row="2" column="1">
+       <property name="text">
+        <string>020320</string>
+       </property>
+      </item>
+      <item row="2" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="3" column="0">
+       <property name="text">
+        <string>浼氳鏍哥畻鏂归潰</string>
+       </property>
+      </item>
+      <item row="3" column="1">
+       <property name="text">
+        <string>020321</string>
+       </property>
+      </item>
+      <item row="3" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="4" column="0">
+       <property name="text">
+        <string>杩濊浣跨敤璧勯噾</string>
+       </property>
+      </item>
+      <item row="4" column="1">
+       <property name="text">
+        <string>020322</string>
+       </property>
+      </item>
+      <item row="4" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="5" column="0">
+       <property name="text">
+        <string>鎴暀銆佹矇娣�璧勯噾</string>
+       </property>
+      </item>
+      <item row="5" column="1">
+       <property name="text">
+        <string>020323</string>
+       </property>
+      </item>
+      <item row="5" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="6" column="0">
+       <property name="text">
+        <string>鎹熷け娴垂</string>
+       </property>
+      </item>
+      <item row="6" column="1">
+       <property name="text">
+        <string>020324</string>
+       </property>
+      </item>
+      <item row="6" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="7" column="0">
+       <property name="text">
+        <string>鎸敤璧勯噾</string>
+       </property>
+      </item>
+      <item row="7" column="1">
+       <property name="text">
+        <string>020325</string>
+       </property>
+      </item>
+      <item row="7" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="8" column="0">
+       <property name="text">
+        <string>鍋锋紡绋庤垂</string>
+       </property>
+      </item>
+      <item row="8" column="1">
+       <property name="text">
+        <string>020326</string>
+       </property>
+      </item>
+      <item row="8" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="9" column="0">
+       <property name="text">
+        <string>杩濊鍙栧緱鏀跺叆</string>
+       </property>
+      </item>
+      <item row="9" column="1">
+       <property name="text">
+        <string>020327</string>
+       </property>
+      </item>
+      <item row="9" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="10" column="0">
+       <property name="text">
+        <string>鍏朵粬</string>
+       </property>
+      </item>
+      <item row="10" column="1">
+       <property name="text">
+        <string>020328</string>
+       </property>
+      </item>
+      <item row="10" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+     </widget>
     </item>
-    <item row="1" column="1">
-     <property name="text">
-      <string>020310</string>
-     </property>
-    </item>
-    <item row="1" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="2" column="0">
-     <property name="text">
-      <string>鍚堣鎬ч棶棰橀噾棰�</string>
-     </property>
-    </item>
-    <item row="2" column="1">
-     <property name="text">
-      <string>020320</string>
-     </property>
-    </item>
-    <item row="2" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="3" column="0">
-     <property name="text">
-      <string>浼氳鏍哥畻鏂归潰</string>
-     </property>
-    </item>
-    <item row="3" column="1">
-     <property name="text">
-      <string>020321</string>
-     </property>
-    </item>
-    <item row="3" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="4" column="0">
-     <property name="text">
-      <string>杩濊浣跨敤璧勯噾</string>
-     </property>
-    </item>
-    <item row="4" column="1">
-     <property name="text">
-      <string>020322</string>
-     </property>
-    </item>
-    <item row="4" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="5" column="0">
-     <property name="text">
-      <string>鎴暀銆佹矇娣�璧勯噾</string>
-     </property>
-    </item>
-    <item row="5" column="1">
-     <property name="text">
-      <string>020323</string>
-     </property>
-    </item>
-    <item row="5" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="6" column="0">
-     <property name="text">
-      <string>鎹熷け娴垂</string>
-     </property>
-    </item>
-    <item row="6" column="1">
-     <property name="text">
-      <string>020324</string>
-     </property>
-    </item>
-    <item row="6" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="7" column="0">
-     <property name="text">
-      <string>鎸敤璧勯噾</string>
-     </property>
-    </item>
-    <item row="7" column="1">
-     <property name="text">
-      <string>020325</string>
-     </property>
-    </item>
-    <item row="7" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="8" column="0">
-     <property name="text">
-      <string>鍋锋紡绋庤垂</string>
-     </property>
-    </item>
-    <item row="8" column="1">
-     <property name="text">
-      <string>020326</string>
-     </property>
-    </item>
-    <item row="8" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="9" column="0">
-     <property name="text">
-      <string>杩濊鍙栧緱鏀跺叆</string>
-     </property>
-    </item>
-    <item row="9" column="1">
-     <property name="text">
-      <string>020327</string>
-     </property>
-    </item>
-    <item row="9" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="10" column="0">
-     <property name="text">
-      <string>鍏朵粬</string>
-     </property>
-    </item>
-    <item row="10" column="1">
-     <property name="text">
-      <string>020328</string>
-     </property>
-    </item>
-    <item row="10" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-   </widget>
+   </layout>
   </widget>
   <widget class="QMenuBar" name="menubar">
    <property name="geometry">
diff --git a/internal_system_v1/problemnotmoney.cpp b/internal_system_v1/problemnotmoney.cpp
index 50539d1..21e6c3f 100644
--- a/internal_system_v1/problemnotmoney.cpp
+++ b/internal_system_v1/problemnotmoney.cpp
@@ -6,9 +6,19 @@
     ui(new Ui::ProblemNotMoney)
 {
     ui->setupUi(this);
+    ui->tableWidget->setColumnWidth(0,300);
 }
 
 ProblemNotMoney::~ProblemNotMoney()
 {
     delete ui;
 }
+
+void ProblemNotMoney::on_tableWidget_clicked(const QModelIndex &index)
+{
+    int allCnt = 0;
+    for(int i=1;i<ui->tableWidget->rowCount();++i){
+        allCnt += ui->tableWidget->item(i,2)->text().toInt();
+    }
+    ui->tableWidget->setItem(0,2,new QTableWidgetItem(QString::number(allCnt)));
+}
diff --git a/internal_system_v1/problemnotmoney.h b/internal_system_v1/problemnotmoney.h
index 8941fdb..9bc6126 100644
--- a/internal_system_v1/problemnotmoney.h
+++ b/internal_system_v1/problemnotmoney.h
@@ -15,6 +15,9 @@
     explicit ProblemNotMoney(QWidget *parent = 0);
     ~ProblemNotMoney();
 
+private slots:
+    void on_tableWidget_clicked(const QModelIndex &index);
+
 private:
     Ui::ProblemNotMoney *ui;
 };
diff --git a/internal_system_v1/problemnotmoney.ui b/internal_system_v1/problemnotmoney.ui
index ad532ec..794dbce 100644
--- a/internal_system_v1/problemnotmoney.ui
+++ b/internal_system_v1/problemnotmoney.ui
@@ -14,19 +14,142 @@
    <string>MainWindow</string>
   </property>
   <widget class="QWidget" name="centralwidget">
-   <widget class="QLabel" name="label">
-    <property name="geometry">
-     <rect>
-      <x>120</x>
-      <y>80</y>
-      <width>481</width>
-      <height>111</height>
-     </rect>
-    </property>
-    <property name="text">
-     <string>闂鏁存敼闈為噾棰�</string>
-    </property>
-   </widget>
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QLabel" name="label">
+      <property name="text">
+       <string>闂鏁存敼闈為噾棰�</string>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="0">
+     <widget class="QTableWidget" name="tableWidget">
+      <attribute name="verticalHeaderVisible">
+       <bool>false</bool>
+      </attribute>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <column>
+       <property name="text">
+        <string>鎸囨爣鍚嶇О</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>浠g爜</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>鏁伴噺(涓�)</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>涓婁紶浣愯瘉璧勬枡</string>
+       </property>
+      </column>
+      <item row="0" column="0">
+       <property name="text">
+        <string>瀹¤鍙戠幇闂鏁存敼锛堥潪閲戦绫伙級</string>
+       </property>
+      </item>
+      <item row="0" column="1">
+       <property name="text">
+        <string>020600</string>
+       </property>
+      </item>
+      <item row="0" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="1" column="0">
+       <property name="text">
+        <string>鏂板埗瀹氬埗搴�</string>
+       </property>
+      </item>
+      <item row="1" column="1">
+       <property name="text">
+        <string>020601</string>
+       </property>
+      </item>
+      <item row="1" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="2" column="0">
+       <property name="text">
+        <string>淇瀹屽杽鍒跺害</string>
+       </property>
+      </item>
+      <item row="2" column="1">
+       <property name="text">
+        <string>020602</string>
+       </property>
+      </item>
+      <item row="2" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="3" column="0">
+       <property name="text">
+        <string>浼樺寲瀹屽杽涓氬姟娴佺▼</string>
+       </property>
+      </item>
+      <item row="3" column="1">
+       <property name="text">
+        <string>020603</string>
+       </property>
+      </item>
+      <item row="3" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="4" column="0">
+       <property name="text">
+        <string>鍏朵粬</string>
+       </property>
+      </item>
+      <item row="4" column="1">
+       <property name="text">
+        <string>020604</string>
+       </property>
+      </item>
+      <item row="4" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+     </widget>
+    </item>
+   </layout>
   </widget>
   <widget class="QMenuBar" name="menubar">
    <property name="geometry">
@@ -34,7 +157,7 @@
      <x>0</x>
      <y>0</y>
      <width>800</width>
-     <height>25</height>
+     <height>26</height>
     </rect>
    </property>
   </widget>
diff --git a/internal_system_v1/problemrectification.ui b/internal_system_v1/problemrectification.ui
index 8caa809..177c1b7 100644
--- a/internal_system_v1/problemrectification.ui
+++ b/internal_system_v1/problemrectification.ui
@@ -14,192 +14,182 @@
    <string>MainWindow</string>
   </property>
   <widget class="QWidget" name="centralwidget">
-   <widget class="QLabel" name="label">
-    <property name="geometry">
-     <rect>
-      <x>110</x>
-      <y>20</y>
-      <width>521</width>
-      <height>111</height>
-     </rect>
-    </property>
-    <property name="text">
-     <string>闂鏁存敼</string>
-    </property>
-   </widget>
-   <widget class="QTableWidget" name="tableWidget">
-    <property name="geometry">
-     <rect>
-      <x>20</x>
-      <y>120</y>
-      <width>761</width>
-      <height>441</height>
-     </rect>
-    </property>
-    <attribute name="verticalHeaderVisible">
-     <bool>false</bool>
-    </attribute>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <row>
-     <property name="text">
-      <string>鏂板缓琛�</string>
-     </property>
-    </row>
-    <column>
-     <property name="text">
-      <string>鎸囨爣鍚嶇О</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>浠g爜</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>鏁伴噺(鍏�)</string>
-     </property>
-    </column>
-    <column>
-     <property name="text">
-      <string>涓婁紶浣愯瘉璧勬枡</string>
-     </property>
-    </column>
+   <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="0">
-     <property name="text">
-      <string>瀹¤鍙戠幇闂鏁存敼锛堥噾棰濈被锛�</string>
-     </property>
-    </item>
-    <item row="0" column="1">
-     <property name="text">
-      <string>020500</string>
-     </property>
-    </item>
-    <item row="0" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
+     <widget class="QLabel" name="label">
+      <property name="text">
+       <string>闂鏁存敼</string>
+      </property>
+     </widget>
     </item>
     <item row="1" column="0">
-     <property name="text">
-      <string>璋冩暣浼氳璐︾洰</string>
-     </property>
+     <widget class="QTableWidget" name="tableWidget">
+      <attribute name="verticalHeaderVisible">
+       <bool>false</bool>
+      </attribute>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <column>
+       <property name="text">
+        <string>鎸囨爣鍚嶇О</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>浠g爜</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>鏁伴噺(鍏�)</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>涓婁紶浣愯瘉璧勬枡</string>
+       </property>
+      </column>
+      <item row="0" column="0">
+       <property name="text">
+        <string>瀹¤鍙戠幇闂鏁存敼锛堥噾棰濈被锛�</string>
+       </property>
+      </item>
+      <item row="0" column="1">
+       <property name="text">
+        <string>020500</string>
+       </property>
+      </item>
+      <item row="0" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="1" column="0">
+       <property name="text">
+        <string>璋冩暣浼氳璐︾洰</string>
+       </property>
+      </item>
+      <item row="1" column="1">
+       <property name="text">
+        <string>020501</string>
+       </property>
+      </item>
+      <item row="1" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="2" column="0">
+       <property name="text">
+        <string>鏀跺洖璧勯噾</string>
+       </property>
+      </item>
+      <item row="2" column="1">
+       <property name="text">
+        <string>020502</string>
+       </property>
+      </item>
+      <item row="2" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="3" column="0">
+       <property name="text">
+        <string>鎸藉洖鎹熷け</string>
+       </property>
+      </item>
+      <item row="3" column="1">
+       <property name="text">
+        <string>020503</string>
+       </property>
+      </item>
+      <item row="3" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="4" column="0">
+       <property name="text">
+        <string>褰掕繕鍘熻祫閲戞笭閬�</string>
+       </property>
+      </item>
+      <item row="4" column="1">
+       <property name="text">
+        <string>020504</string>
+       </property>
+      </item>
+      <item row="4" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="5" column="0">
+       <property name="text">
+        <string>琛ョ即绋庤垂</string>
+       </property>
+      </item>
+      <item row="5" column="1">
+       <property name="text">
+        <string>020505</string>
+       </property>
+      </item>
+      <item row="5" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="6" column="0">
+       <property name="text">
+        <string>鍏朵粬</string>
+       </property>
+      </item>
+      <item row="6" column="1">
+       <property name="text">
+        <string>020506</string>
+       </property>
+      </item>
+      <item row="6" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+     </widget>
     </item>
-    <item row="1" column="1">
-     <property name="text">
-      <string>020501</string>
-     </property>
-    </item>
-    <item row="1" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="2" column="0">
-     <property name="text">
-      <string>鏀跺洖璧勯噾</string>
-     </property>
-    </item>
-    <item row="2" column="1">
-     <property name="text">
-      <string>020502</string>
-     </property>
-    </item>
-    <item row="2" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="3" column="0">
-     <property name="text">
-      <string>鎸藉洖鎹熷け</string>
-     </property>
-    </item>
-    <item row="3" column="1">
-     <property name="text">
-      <string>020503</string>
-     </property>
-    </item>
-    <item row="3" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="4" column="0">
-     <property name="text">
-      <string>褰掕繕鍘熻祫閲戞笭閬�</string>
-     </property>
-    </item>
-    <item row="4" column="1">
-     <property name="text">
-      <string>020504</string>
-     </property>
-    </item>
-    <item row="4" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="5" column="0">
-     <property name="text">
-      <string>琛ョ即绋庤垂</string>
-     </property>
-    </item>
-    <item row="5" column="1">
-     <property name="text">
-      <string>020505</string>
-     </property>
-    </item>
-    <item row="5" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-    <item row="6" column="0">
-     <property name="text">
-      <string>鍏朵粬</string>
-     </property>
-    </item>
-    <item row="6" column="1">
-     <property name="text">
-      <string>020506</string>
-     </property>
-    </item>
-    <item row="6" column="2">
-     <property name="text">
-      <string>0</string>
-     </property>
-    </item>
-   </widget>
+   </layout>
   </widget>
   <widget class="QMenuBar" name="menubar">
    <property name="geometry">
diff --git a/internal_system_v1/punish.cpp b/internal_system_v1/punish.cpp
index e847f57..3657d19 100644
--- a/internal_system_v1/punish.cpp
+++ b/internal_system_v1/punish.cpp
@@ -6,9 +6,19 @@
     ui(new Ui::Punish)
 {
     ui->setupUi(this);
+    ui->tableWidget->setColumnWidth(0,320);
 }
 
 Punish::~Punish()
 {
     delete ui;
 }
+
+void Punish::on_tableWidget_clicked(const QModelIndex &index)
+{
+    int allCnt = 0;
+    for(int i=1;i<ui->tableWidget->rowCount();++i){
+        allCnt += ui->tableWidget->item(i,2)->text().toInt();
+    }
+    ui->tableWidget->setItem(0,2,new QTableWidgetItem(QString::number(allCnt)));
+}
diff --git a/internal_system_v1/punish.h b/internal_system_v1/punish.h
index fba87a1..1ce3044 100644
--- a/internal_system_v1/punish.h
+++ b/internal_system_v1/punish.h
@@ -15,6 +15,9 @@
     explicit Punish(QWidget *parent = 0);
     ~Punish();
 
+private slots:
+    void on_tableWidget_clicked(const QModelIndex &index);
+
 private:
     Ui::Punish *ui;
 };
diff --git a/internal_system_v1/punish.ui b/internal_system_v1/punish.ui
index bb11262..6af124a 100644
--- a/internal_system_v1/punish.ui
+++ b/internal_system_v1/punish.ui
@@ -14,19 +14,117 @@
    <string>MainWindow</string>
   </property>
   <widget class="QWidget" name="centralwidget">
-   <widget class="QLabel" name="label">
-    <property name="geometry">
-     <rect>
-      <x>130</x>
-      <y>80</y>
-      <width>511</width>
-      <height>151</height>
-     </rect>
-    </property>
-    <property name="text">
-     <string>澶勫垎</string>
-    </property>
-   </widget>
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QLabel" name="label">
+      <property name="text">
+       <string>澶勫垎</string>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="0">
+     <widget class="QTableWidget" name="tableWidget">
+      <attribute name="verticalHeaderVisible">
+       <bool>false</bool>
+      </attribute>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <row>
+       <property name="text">
+        <string>鏂板缓琛�</string>
+       </property>
+      </row>
+      <column>
+       <property name="text">
+        <string>鎸囨爣鍚嶇О</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>浠g爜</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>鏁伴噺(浜�)</string>
+       </property>
+      </column>
+      <item row="0" column="0">
+       <property name="text">
+        <string>鏍规嵁瀹¤寤鸿缁欎簣鍏氱邯銆佹斂鍔″拰鍐呴儴绾緥澶勫垎</string>
+       </property>
+      </item>
+      <item row="0" column="1">
+       <property name="text">
+        <string>020700</string>
+       </property>
+      </item>
+      <item row="0" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="1" column="0">
+       <property name="text">
+        <string>鍏氱邯澶勫垎</string>
+       </property>
+      </item>
+      <item row="1" column="1">
+       <property name="text">
+        <string>020701</string>
+       </property>
+      </item>
+      <item row="1" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="2" column="0">
+       <property name="text">
+        <string>鏀垮姟澶勫垎</string>
+       </property>
+      </item>
+      <item row="2" column="1">
+       <property name="text">
+        <string>020702</string>
+       </property>
+      </item>
+      <item row="2" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+      <item row="3" column="0">
+       <property name="text">
+        <string>鍐呴儴绾緥澶勫垎</string>
+       </property>
+      </item>
+      <item row="3" column="1">
+       <property name="text">
+        <string>020703</string>
+       </property>
+      </item>
+      <item row="3" column="2">
+       <property name="text">
+        <string>0</string>
+       </property>
+      </item>
+     </widget>
+    </item>
+   </layout>
   </widget>
   <widget class="QMenuBar" name="menubar">
    <property name="geometry">
@@ -34,7 +132,7 @@
      <x>0</x>
      <y>0</y>
      <width>800</width>
-     <height>25</height>
+     <height>26</height>
     </rect>
    </property>
   </widget>

--
Gitblit v1.8.0