mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
Merge branch 'master' into memory_leaks_fix
This commit is contained in:
commit
1868128dda
78
.circleci/config.yml
Normal file
78
.circleci/config.yml
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
version: 2.1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
docker:
|
||||||
|
- image: lycantropos/cmake:3.9.5
|
||||||
|
parameters:
|
||||||
|
benchmarks:
|
||||||
|
default: "OFF"
|
||||||
|
type: string
|
||||||
|
build-type:
|
||||||
|
default: Release
|
||||||
|
type: string
|
||||||
|
coverage:
|
||||||
|
default: "OFF"
|
||||||
|
type: string
|
||||||
|
cxx-ver:
|
||||||
|
default: "11"
|
||||||
|
type: string
|
||||||
|
samples:
|
||||||
|
default: "OFF"
|
||||||
|
type: string
|
||||||
|
static:
|
||||||
|
default: "ON"
|
||||||
|
type: string
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: cmake -D XLNT_CXX_LANG=<< parameters.cxx-ver >> -D STATIC=<< parameters.static >> -D BENCHMARKS=<< parameters.benchmarks >> -D SAMPLES=<< parameters.samples >> -D COVERAGE=<< parameters.coverage >> -D CMAKE_BUILD_TYPE=<< parameters.build-type >> .
|
||||||
|
- run: cmake --build . -- -j2
|
||||||
|
- run: ./tests/xlnt.test
|
||||||
|
- when:
|
||||||
|
condition:
|
||||||
|
equal: [ "ON", << parameters.samples >> ]
|
||||||
|
steps:
|
||||||
|
- run: ./samples/sample-decrypt
|
||||||
|
- run: ./samples/sample-img2xlsx ./samples/data/penguin.jpg img.xlsx
|
||||||
|
- run: ./samples/sample-documentation
|
||||||
|
- when:
|
||||||
|
condition:
|
||||||
|
equal: [ "ON", << parameters.benchmarks >> ]
|
||||||
|
steps:
|
||||||
|
- run: ./benchmarks/benchmark-styles
|
||||||
|
- run: ./benchmarks/benchmark-writer
|
||||||
|
- when:
|
||||||
|
condition:
|
||||||
|
equal: [ "ON", << parameters.coverage >> ]
|
||||||
|
steps:
|
||||||
|
- run: lcov --directory source/CMakeFiles/xlnt.dir --capture --output-file coverage.info --base-directory ../source --no-external --gcov-tool /usr/bin/gcov-6
|
||||||
|
- run: lcov --output-file coverage.info --remove coverage.info source/detail/serialization/miniz.cpp
|
||||||
|
- run: i=$(dirname $(pwd))
|
||||||
|
- run: sed -i "s|$i/||" coverage.info
|
||||||
|
- run: cd ..
|
||||||
|
- run: coveralls-lcov build/coverage.info
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
build:
|
||||||
|
jobs:
|
||||||
|
- build:
|
||||||
|
name: tests
|
||||||
|
matrix:
|
||||||
|
parameters:
|
||||||
|
cxx-ver:
|
||||||
|
- "11"
|
||||||
|
- "17"
|
||||||
|
build-type:
|
||||||
|
- Release
|
||||||
|
- Debug
|
||||||
|
static:
|
||||||
|
- "ON"
|
||||||
|
- "OFF"
|
||||||
|
- build:
|
||||||
|
name: samples-benchmarks-coverage
|
||||||
|
cxx-ver: "11"
|
||||||
|
build-type: Debug
|
||||||
|
static: "ON"
|
||||||
|
samples: "ON"
|
||||||
|
benchmarks: "ON"
|
||||||
|
coverage: "OFF"
|
231
.travis.yml
231
.travis.yml
@ -1,231 +0,0 @@
|
|||||||
# cpp takes longer
|
|
||||||
language: minimal
|
|
||||||
sudo: false
|
|
||||||
dist: trusty
|
|
||||||
|
|
||||||
git:
|
|
||||||
depth: false
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
||||||
|
|
||||||
# set up build matrix
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
# ============= GCC ==================
|
|
||||||
# gcc-5, c++11, release build, dynamic linking
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
packages:
|
|
||||||
- g++-5
|
|
||||||
env:
|
|
||||||
- CXX_COMPILER=g++-5
|
|
||||||
- C_COMPILER=gcc-5
|
|
||||||
- CXX_VER=11
|
|
||||||
- BUILD_TYPE=Release
|
|
||||||
- COVERAGE=OFF
|
|
||||||
- STATIC=OFF
|
|
||||||
- SAMPLES=OFF
|
|
||||||
- BENCHMARKS=OFF
|
|
||||||
- RELEASE=OFF
|
|
||||||
|
|
||||||
# ============= GCC ==================
|
|
||||||
# gcc-6, c++11, release build, dynamic linking
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
packages:
|
|
||||||
- g++-6
|
|
||||||
env:
|
|
||||||
- CXX_COMPILER=g++-6
|
|
||||||
- C_COMPILER=gcc-6
|
|
||||||
- CXX_VER=11
|
|
||||||
- BUILD_TYPE=Release
|
|
||||||
- COVERAGE=OFF
|
|
||||||
- STATIC=OFF
|
|
||||||
- SAMPLES=OFF
|
|
||||||
- BENCHMARKS=OFF
|
|
||||||
- RELEASE=OFF
|
|
||||||
|
|
||||||
# gcc-7, c++14, release build, static linking
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
packages:
|
|
||||||
- g++-7
|
|
||||||
env:
|
|
||||||
- CXX_COMPILER=g++-7
|
|
||||||
- C_COMPILER=gcc-7
|
|
||||||
- CXX_VER=14
|
|
||||||
- BUILD_TYPE=Release
|
|
||||||
- COVERAGE=OFF
|
|
||||||
- STATIC=ON
|
|
||||||
- SAMPLES=OFF
|
|
||||||
- BENCHMARKS=OFF
|
|
||||||
- RELEASE=OFF
|
|
||||||
|
|
||||||
# gcc-8, c++17, release build, static linking, samples + benchmarks compiled and run
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
packages:
|
|
||||||
- g++-8
|
|
||||||
env:
|
|
||||||
- CXX_COMPILER=g++-8
|
|
||||||
- C_COMPILER=gcc-8
|
|
||||||
- CXX_VER=17
|
|
||||||
- BUILD_TYPE=Release
|
|
||||||
- COVERAGE=OFF
|
|
||||||
- STATIC=ON
|
|
||||||
- SAMPLES=ON
|
|
||||||
- BENCHMARKS=ON
|
|
||||||
- RELEASE=ON
|
|
||||||
|
|
||||||
# =========== CLANG =============
|
|
||||||
# clang 4, c++11, release build, dynamic linking
|
|
||||||
- os: linux
|
|
||||||
compiler: clang
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
- llvm-toolchain-trusty-4.0
|
|
||||||
packages:
|
|
||||||
- clang-4.0
|
|
||||||
env:
|
|
||||||
- CXX_COMPILER=clang++-4.0
|
|
||||||
- C_COMPILER=clang-4.0
|
|
||||||
- CXX_VER=11
|
|
||||||
- BUILD_TYPE=Release
|
|
||||||
- COVERAGE=OFF
|
|
||||||
- STATIC=OFF
|
|
||||||
- SAMPLES=OFF
|
|
||||||
- BENCHMARKS=OFF
|
|
||||||
- RELEASE=OFF
|
|
||||||
|
|
||||||
# clang 5, c++14, release build, dynamic linking
|
|
||||||
- os: linux
|
|
||||||
compiler: clang
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
- llvm-toolchain-trusty-5.0
|
|
||||||
packages:
|
|
||||||
- clang-5.0
|
|
||||||
env:
|
|
||||||
- CXX_COMPILER=clang++-5.0
|
|
||||||
- C_COMPILER=clang-5.0
|
|
||||||
- CXX_VER=14
|
|
||||||
- BUILD_TYPE=Release
|
|
||||||
- COVERAGE=OFF
|
|
||||||
- STATIC=ON
|
|
||||||
- SAMPLES=OFF
|
|
||||||
- BENCHMARKS=OFF
|
|
||||||
- RELEASE=OFF
|
|
||||||
|
|
||||||
# clang 6, c++17, release build, static linking, samples + benchmarks compiled and run
|
|
||||||
- os: linux
|
|
||||||
compiler: clang
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
- llvm-toolchain-trusty-6.0
|
|
||||||
packages:
|
|
||||||
- clang-6.0
|
|
||||||
env:
|
|
||||||
- CXX_COMPILER=clang++-6.0
|
|
||||||
- C_COMPILER=clang-6.0
|
|
||||||
- CXX_VER=17
|
|
||||||
- BUILD_TYPE=Release
|
|
||||||
- COVERAGE=OFF
|
|
||||||
- STATIC=ON
|
|
||||||
- SAMPLES=ON
|
|
||||||
- BENCHMARKS=ON
|
|
||||||
- RELEASE=ON
|
|
||||||
|
|
||||||
# ============= CODE COVERAGE ===============
|
|
||||||
# gcc-6, c++11, debug build, static linking, code coverage enabled
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
packages:
|
|
||||||
- g++-6
|
|
||||||
- lcov
|
|
||||||
env:
|
|
||||||
- CXX_COMPILER=g++-6
|
|
||||||
- C_COMPILER=gcc-6
|
|
||||||
- CXX_VER=11
|
|
||||||
- BUILD_TYPE=Debug
|
|
||||||
- COVERAGE=ON
|
|
||||||
- STATIC=ON
|
|
||||||
- SAMPLES=OFF
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- export CC=${C_COMPILER}
|
|
||||||
- export CXX=${CXX_COMPILER}
|
|
||||||
|
|
||||||
install:
|
|
||||||
- |
|
|
||||||
if [[ "${COVERAGE}" == "ON" ]]; then
|
|
||||||
gem install coveralls-lcov;
|
|
||||||
fi
|
|
||||||
- ${CXX} --version
|
|
||||||
- cmake --version
|
|
||||||
|
|
||||||
script:
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- cmake .. -DXLNT_CXX_LANG=${CXX_VER} -DSTATIC=$STATIC -DBENCHMARKS=$BENCHMARKS -DSAMPLES=$SAMPLES -DCOVERAGE=$COVERAGE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DRELEASE=$RELEASE
|
|
||||||
- cmake --build . -- -j2
|
|
||||||
- ./tests/xlnt.test
|
|
||||||
- echo "samples" && echo 'travis_fold:start:samples'
|
|
||||||
- if [[ "${SAMPLES}" == "ON" ]]; then ./samples/sample-decrypt; fi
|
|
||||||
- if [[ "${SAMPLES}" == "ON" ]]; then ./samples/sample-img2xlsx "../samples/data/cafe.jpg" "img.xlsx"; fi
|
|
||||||
- if [[ "${SAMPLES}" == "ON" ]]; then ./samples/sample-documentation; fi
|
|
||||||
- echo 'travis_fold:end:samples'
|
|
||||||
- echo "benchmarks" && echo 'travis_fold:start:benchmarks'
|
|
||||||
- if [[ "${BENCHMARKS}" == "ON" ]]; then ./benchmarks/benchmark-styles; fi
|
|
||||||
- if [[ "${BENCHMARKS}" == "ON" ]]; then ./benchmarks/benchmark-writer; fi
|
|
||||||
- echo 'travis_fold:end:benchmarks'
|
|
||||||
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- |
|
|
||||||
if [[ "${COVERAGE}" == "ON" ]]; then
|
|
||||||
lcov --directory source/CMakeFiles/xlnt.dir --capture --output-file coverage.info --base-directory ../source --no-external --gcov-tool /usr/bin/gcov-6
|
|
||||||
lcov --output-file coverage.info --remove coverage.info source/detail/serialization/miniz.cpp
|
|
||||||
i=$(dirname $(pwd))
|
|
||||||
sed -i "s|$i/||" coverage.info
|
|
||||||
cd ..
|
|
||||||
coveralls-lcov build/coverage.info
|
|
||||||
fi
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: "EJKEQkbmNFyXAJYOro7/wSlxSns4O4RAmht5PCBYuOgEqIbB1+QbQjNZd18KyCkqaHQEvww4hVGMdcFsTFnsznjGo6NnDtiYTdhiREtdUd6ohUD0eHTZ15ZL7mW1XR8HWqvv33piDX40UI/dFn1XYLnWunaLZvF5WPa9bzTsloaYHbjxoRw5S4fd0VyqZ2w2zuezCCRUezDcNGOxbVTbB3moSh+hpjrNkw7YxoPNm48CwGRVeRj28XuhDjobfRtPSZMb6Y+EDUnrIZI1mKvB1bkL8QR2ndBtqlG0BWvmEcdDuiQnraJk3iRIAU5T/ycyRqR2UKcW2Fv0iVp5SL9VuqhcvIUxTsYXzuNOZ3hKiWRTj6ndG+gDBsD1K5YwScZksAImwvj/VGEla9Q044W3PbYV2GUE++8mtiZUaxbkaP+uDFUBR5eXqAkte9mainwJ3eaMJ7Tx1KCqkzKO011nUasWfmBWxRUA8vm44SfzwzVfjXToLQZGe4KYzF2cHaXo2YIC48vE/DYs3VnVvnrCjNDO8Cr3m+lfdulhjIZlg+WymQcxuJs7LVzCW7mBPNnrUNOOrGCGP4f/hFxBLk8/eJDznIAzbW27Z1zAHn+MlbADRBzC0Y7cmme4Zu2W7Wy9NTvzNsKabOH/Fe1TfGetEEf6mZ5g7Q3+oZPJ2raLFD8="
|
|
||||||
file_glob: true
|
|
||||||
file: build/*.tar.gz
|
|
||||||
skip_cleanup: true
|
|
||||||
overwite: true
|
|
||||||
on:
|
|
||||||
repo: tfussell/xlnt
|
|
||||||
tags: true
|
|
@ -38,7 +38,8 @@ namespace xlnt {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class optional
|
class optional
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1900 // v14, visual studio 2015
|
#if ((defined(_MSC_VER) && _MSC_VER <= 1900) || (defined(__GNUC__) && __GNUC__ < 5))
|
||||||
|
// Disable enhanced type checking on Visual Studio <= 2015 and GCC <5
|
||||||
#define XLNT_NOEXCEPT_VALUE_COMPAT(...) (false)
|
#define XLNT_NOEXCEPT_VALUE_COMPAT(...) (false)
|
||||||
#else
|
#else
|
||||||
#define XLNT_NOEXCEPT_VALUE_COMPAT(...) (__VA_ARGS__)
|
#define XLNT_NOEXCEPT_VALUE_COMPAT(...) (__VA_ARGS__)
|
||||||
|
@ -241,6 +241,13 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
const worksheet sheet_by_id(std::size_t id) const;
|
const worksheet sheet_by_id(std::size_t id) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the hidden identifier of the worksheet at the given index.
|
||||||
|
/// This will throw an exception if index is greater than or equal to the
|
||||||
|
/// number of sheets in this workbook.
|
||||||
|
/// </summary>
|
||||||
|
bool sheet_hidden_by_index(std::size_t index) const;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true if this workbook contains a sheet with the given title.
|
/// Returns true if this workbook contains a sheet with the given title.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -760,11 +767,6 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
std::size_t add_shared_string(const rich_text &shared, bool allow_duplicates = false);
|
std::size_t add_shared_string(const rich_text &shared, bool allow_duplicates = false);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a reference to the shared string ordered by id
|
|
||||||
/// </summary>
|
|
||||||
const std::map<std::size_t, rich_text> &shared_strings_by_id() const;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a reference to the shared string related to the specified index
|
/// Returns a reference to the shared string related to the specified index
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -774,13 +776,13 @@ public:
|
|||||||
/// Returns a reference to the shared strings being used by cells
|
/// Returns a reference to the shared strings being used by cells
|
||||||
/// in this workbook.
|
/// in this workbook.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
std::unordered_map<rich_text, std::size_t, rich_text_hash> &shared_strings();
|
std::vector<rich_text> &shared_strings();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a reference to the shared strings being used by cells
|
/// Returns a reference to the shared strings being used by cells
|
||||||
/// in this workbook.
|
/// in this workbook.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
const std::unordered_map<rich_text, std::size_t, rich_text_hash> &shared_strings() const;
|
const std::vector<rich_text> &shared_strings() const;
|
||||||
|
|
||||||
// Thumbnail
|
// Thumbnail
|
||||||
|
|
||||||
|
@ -770,6 +770,12 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
bool has_drawing() const;
|
bool has_drawing() const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this worksheet is empty.
|
||||||
|
/// A worksheet is considered empty if it doesn't have any cells.
|
||||||
|
/// </summary>
|
||||||
|
bool is_empty() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class cell;
|
friend class cell;
|
||||||
friend class const_range_iterator;
|
friend class const_range_iterator;
|
||||||
|
1861
package-lock.json
generated
1861
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -9,8 +9,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@release-it/bumper": "^1.1.0",
|
"@release-it/bumper": "^2.0.0",
|
||||||
"release-it": "^13.1.1"
|
"release-it": "^14.2.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"release": "release-it"
|
"release": "release-it"
|
||||||
|
BIN
samples/data/penguin.jpg
Normal file
BIN
samples/data/penguin.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
@ -174,7 +174,8 @@ void sha1_hash(const uint8_t *message, size_t len, uint32_t hash[5]) {
|
|||||||
|
|
||||||
block[BLOCK_SIZE - 1] = (uint8_t)((len & 0x1FU) << 3);
|
block[BLOCK_SIZE - 1] = (uint8_t)((len & 0x1FU) << 3);
|
||||||
len >>= 5;
|
len >>= 5;
|
||||||
for (int i = 1; i < LENGTH_SIZE; i++, len >>= 8)
|
int i;
|
||||||
|
for (i = 1; i < LENGTH_SIZE; i++, len >>= 8)
|
||||||
block[BLOCK_SIZE - 1 - i] = (uint8_t)(len & 0xFFU);
|
block[BLOCK_SIZE - 1 - i] = (uint8_t)(len & 0xFFU);
|
||||||
sha1_compress(hash, block);
|
sha1_compress(hash, block);
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,8 @@ void sha512_hash(const uint8_t *message, size_t len, uint64_t hash[8]) {
|
|||||||
|
|
||||||
block[BLOCK_SIZE - 1] = (uint8_t)((len & 0x1FU) << 3);
|
block[BLOCK_SIZE - 1] = (uint8_t)((len & 0x1FU) << 3);
|
||||||
len >>= 5;
|
len >>= 5;
|
||||||
for (int i = 1; i < LENGTH_SIZE; i++, len >>= 8)
|
int i;
|
||||||
|
for (i = 1; i < LENGTH_SIZE; i++, len >>= 8)
|
||||||
block[BLOCK_SIZE - 1 - i] = (uint8_t)(len & 0xFFU);
|
block[BLOCK_SIZE - 1 - i] = (uint8_t)(len & 0xFFU);
|
||||||
sha512_compress(hash, block);
|
sha512_compress(hash, block);
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,7 @@ struct workbook_impl
|
|||||||
manifest_ = other.manifest_;
|
manifest_ = other.manifest_;
|
||||||
|
|
||||||
sheet_title_rel_id_map_ = other.sheet_title_rel_id_map_;
|
sheet_title_rel_id_map_ = other.sheet_title_rel_id_map_;
|
||||||
|
sheet_hidden_ = other.sheet_hidden_;
|
||||||
view_ = other.view_;
|
view_ = other.view_;
|
||||||
code_name_ = other.code_name_;
|
code_name_ = other.code_name_;
|
||||||
file_version_ = other.file_version_;
|
file_version_ = other.file_version_;
|
||||||
@ -105,6 +106,7 @@ struct workbook_impl
|
|||||||
&& extended_properties_ == other.extended_properties_
|
&& extended_properties_ == other.extended_properties_
|
||||||
&& custom_properties_ == other.custom_properties_
|
&& custom_properties_ == other.custom_properties_
|
||||||
&& sheet_title_rel_id_map_ == other.sheet_title_rel_id_map_
|
&& sheet_title_rel_id_map_ == other.sheet_title_rel_id_map_
|
||||||
|
&& sheet_hidden_ == other.sheet_hidden_
|
||||||
&& view_ == other.view_
|
&& view_ == other.view_
|
||||||
&& code_name_ == other.code_name_
|
&& code_name_ == other.code_name_
|
||||||
&& file_version_ == other.file_version_
|
&& file_version_ == other.file_version_
|
||||||
@ -118,7 +120,7 @@ struct workbook_impl
|
|||||||
|
|
||||||
std::list<worksheet_impl> worksheets_;
|
std::list<worksheet_impl> worksheets_;
|
||||||
std::unordered_map<rich_text, std::size_t, rich_text_hash> shared_strings_ids_;
|
std::unordered_map<rich_text, std::size_t, rich_text_hash> shared_strings_ids_;
|
||||||
std::map<std::size_t, rich_text> shared_strings_values_;
|
std::vector<rich_text> shared_strings_values_;
|
||||||
|
|
||||||
optional<stylesheet> stylesheet_;
|
optional<stylesheet> stylesheet_;
|
||||||
|
|
||||||
@ -134,16 +136,17 @@ struct workbook_impl
|
|||||||
std::vector<std::pair<std::string, variant>> custom_properties_;
|
std::vector<std::pair<std::string, variant>> custom_properties_;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string> sheet_title_rel_id_map_;
|
std::unordered_map<std::string, std::string> sheet_title_rel_id_map_;
|
||||||
|
std::vector<bool> sheet_hidden_;
|
||||||
|
|
||||||
optional<workbook_view> view_;
|
optional<workbook_view> view_;
|
||||||
optional<std::string> code_name_;
|
optional<std::string> code_name_;
|
||||||
|
|
||||||
struct file_version_t
|
struct file_version_t
|
||||||
{
|
{
|
||||||
std::string app_name;
|
std::string app_name;
|
||||||
std::size_t last_edited;
|
std::size_t last_edited;
|
||||||
std::size_t lowest_edited;
|
std::size_t lowest_edited;
|
||||||
std::size_t rup_build;
|
std::size_t rup_build;
|
||||||
|
|
||||||
bool operator==(const file_version_t& rhs) const
|
bool operator==(const file_version_t& rhs) const
|
||||||
{
|
{
|
||||||
@ -152,7 +155,7 @@ struct workbook_impl
|
|||||||
&& lowest_edited == rhs.lowest_edited
|
&& lowest_edited == rhs.lowest_edited
|
||||||
&& rup_build == rhs.rup_build;
|
&& rup_build == rhs.rup_build;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
optional<file_version_t> file_version_;
|
optional<file_version_t> file_version_;
|
||||||
optional<calculation_properties> calculation_properties_;
|
optional<calculation_properties> calculation_properties_;
|
||||||
|
@ -199,8 +199,8 @@ pattern_fill_type from_string(const std::string &string)
|
|||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
auto toLower = [](std::string str) {
|
auto toLower = [](std::string str) {
|
||||||
auto bg{ std::begin (str) };
|
auto bg = std::begin (str);
|
||||||
auto en{ std::end (str) };
|
auto en = std::end (str);
|
||||||
std::transform(bg, en, bg,
|
std::transform(bg, en, bg,
|
||||||
[](char c) {
|
[](char c) {
|
||||||
// static cast to avoid int -> char narrowing warning
|
// static cast to avoid int -> char narrowing warning
|
||||||
@ -211,7 +211,7 @@ pattern_fill_type from_string(const std::string &string)
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto patternLookup = [](const std::string& key) {
|
auto patternLookup = [](const std::string& key) {
|
||||||
auto entry { patternFill.find (key) };
|
auto entry = patternFill.find (key);
|
||||||
if (entry != std::end (patternFill)) {
|
if (entry != std::end (patternFill)) {
|
||||||
return entry->second;
|
return entry->second;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
// @license: http://www.opensource.org/licenses/mit-license.php
|
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <numeric> // for std::accumulate
|
#include <numeric> // for std::accumulate
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -243,6 +244,11 @@ xlnt::detail::Cell parse_cell(xlnt::row_t row_arg, xml::parser *parser)
|
|||||||
throw xlnt::exception("unexcpected XML parsing event");
|
throw xlnt::exception("unexcpected XML parsing event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Prevents unhandled exceptions from being triggered.
|
||||||
|
for (auto &attr : parser->attribute_map())
|
||||||
|
{
|
||||||
|
(void)attr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@ -406,171 +412,7 @@ void xlsx_consumer::open(std::istream &source)
|
|||||||
|
|
||||||
cell xlsx_consumer::read_cell()
|
cell xlsx_consumer::read_cell()
|
||||||
{
|
{
|
||||||
if (!has_cell())
|
return cell(streaming_cell_.get());
|
||||||
{
|
|
||||||
return cell(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ws = worksheet(current_worksheet_);
|
|
||||||
|
|
||||||
if (in_element(qn("spreadsheetml", "sheetData")))
|
|
||||||
{
|
|
||||||
expect_start_element(qn("spreadsheetml", "row"), xml::content::complex); // CT_Row
|
|
||||||
auto row_index = static_cast<row_t>(std::stoul(parser().attribute("r")));
|
|
||||||
auto &row_properties = ws.row_properties(row_index);
|
|
||||||
|
|
||||||
if (parser().attribute_present("ht"))
|
|
||||||
{
|
|
||||||
row_properties.height = converter_.deserialise(parser().attribute("ht"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser().attribute_present("customHeight"))
|
|
||||||
{
|
|
||||||
row_properties.custom_height = is_true(parser().attribute("customHeight"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser().attribute_present("hidden") && is_true(parser().attribute("hidden")))
|
|
||||||
{
|
|
||||||
row_properties.hidden = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser().attribute_present(qn("x14ac", "dyDescent")))
|
|
||||||
{
|
|
||||||
row_properties.dy_descent = converter_.deserialise(parser().attribute(qn("x14ac", "dyDescent")));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser().attribute_present("spans"))
|
|
||||||
{
|
|
||||||
row_properties.spans = parser().attribute("spans");
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_attributes({"customFormat", "s", "customFont",
|
|
||||||
"outlineLevel", "collapsed", "thickTop", "thickBot",
|
|
||||||
"ph"});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_element(qn("spreadsheetml", "row")))
|
|
||||||
{
|
|
||||||
return cell(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect_start_element(qn("spreadsheetml", "c"), xml::content::complex);
|
|
||||||
|
|
||||||
auto cell = streaming_
|
|
||||||
? xlnt::cell(streaming_cell_.get())
|
|
||||||
: ws.cell(cell_reference(parser().attribute("r")));
|
|
||||||
auto reference = cell_reference(parser().attribute("r"));
|
|
||||||
cell.d_->parent_ = current_worksheet_;
|
|
||||||
cell.d_->column_ = reference.column_index();
|
|
||||||
cell.d_->row_ = reference.row();
|
|
||||||
|
|
||||||
if (parser().attribute_present("ph"))
|
|
||||||
{
|
|
||||||
cell.d_->phonetics_visible_ = parser().attribute<bool>("ph");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto has_type = parser().attribute_present("t");
|
|
||||||
auto type = has_type ? parser().attribute("t") : "n";
|
|
||||||
|
|
||||||
if (parser().attribute_present("s"))
|
|
||||||
{
|
|
||||||
cell.format(target_.format(static_cast<std::size_t>(std::stoull(parser().attribute("s")))));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto has_value = false;
|
|
||||||
auto value_string = std::string();
|
|
||||||
|
|
||||||
auto has_formula = false;
|
|
||||||
auto has_shared_formula = false;
|
|
||||||
auto formula_value_string = std::string();
|
|
||||||
|
|
||||||
while (in_element(qn("spreadsheetml", "c")))
|
|
||||||
{
|
|
||||||
auto current_element = expect_start_element(xml::content::mixed);
|
|
||||||
|
|
||||||
if (current_element == qn("spreadsheetml", "v")) // s:ST_Xstring
|
|
||||||
{
|
|
||||||
has_value = true;
|
|
||||||
value_string = read_text();
|
|
||||||
}
|
|
||||||
else if (current_element == qn("spreadsheetml", "f")) // CT_CellFormula
|
|
||||||
{
|
|
||||||
has_formula = true;
|
|
||||||
|
|
||||||
if (parser().attribute_present("t"))
|
|
||||||
{
|
|
||||||
has_shared_formula = parser().attribute("t") == "shared";
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_attributes({"aca", "ref", "dt2D", "dtr", "del1",
|
|
||||||
"del2", "r1", "r2", "ca", "si", "bx"});
|
|
||||||
|
|
||||||
formula_value_string = read_text();
|
|
||||||
}
|
|
||||||
else if (current_element == qn("spreadsheetml", "is")) // CT_Rst
|
|
||||||
{
|
|
||||||
expect_start_element(qn("spreadsheetml", "t"), xml::content::simple);
|
|
||||||
has_value = true;
|
|
||||||
value_string = read_text();
|
|
||||||
expect_end_element(qn("spreadsheetml", "t"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unexpected_element(current_element);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect_end_element(current_element);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect_end_element(qn("spreadsheetml", "c"));
|
|
||||||
|
|
||||||
if (has_formula && !has_shared_formula)
|
|
||||||
{
|
|
||||||
cell.formula(formula_value_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_value)
|
|
||||||
{
|
|
||||||
if (type == "str")
|
|
||||||
{
|
|
||||||
cell.d_->value_text_ = value_string;
|
|
||||||
cell.data_type(cell::type::formula_string);
|
|
||||||
}
|
|
||||||
else if (type == "inlineStr")
|
|
||||||
{
|
|
||||||
cell.d_->value_text_ = value_string;
|
|
||||||
cell.data_type(cell::type::inline_string);
|
|
||||||
}
|
|
||||||
else if (type == "s")
|
|
||||||
{
|
|
||||||
cell.d_->value_numeric_ = converter_.deserialise(value_string);
|
|
||||||
cell.data_type(cell::type::shared_string);
|
|
||||||
}
|
|
||||||
else if (type == "b") // boolean
|
|
||||||
{
|
|
||||||
cell.value(is_true(value_string));
|
|
||||||
}
|
|
||||||
else if (type == "n") // numeric
|
|
||||||
{
|
|
||||||
cell.value(converter_.deserialise(value_string));
|
|
||||||
}
|
|
||||||
else if (!value_string.empty() && value_string[0] == '#')
|
|
||||||
{
|
|
||||||
cell.error(value_string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_element(qn("spreadsheetml", "row")))
|
|
||||||
{
|
|
||||||
expect_end_element(qn("spreadsheetml", "row"));
|
|
||||||
|
|
||||||
if (!in_element(qn("spreadsheetml", "sheetData")))
|
|
||||||
{
|
|
||||||
expect_end_element(qn("spreadsheetml", "sheetData"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cell;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
||||||
@ -1411,8 +1253,174 @@ xml::parser &xlsx_consumer::parser()
|
|||||||
|
|
||||||
bool xlsx_consumer::has_cell()
|
bool xlsx_consumer::has_cell()
|
||||||
{
|
{
|
||||||
return in_element(qn("spreadsheetml", "row"))
|
auto ws = worksheet(current_worksheet_);
|
||||||
|| in_element(qn("spreadsheetml", "sheetData"));
|
|
||||||
|
while (streaming_cell_ // we're not at the end of the file
|
||||||
|
&& !in_element(qn("spreadsheetml", "row"))) // we're at the end of a row, or between rows
|
||||||
|
{
|
||||||
|
if (parser().peek() == xml::parser::event_type::end_element
|
||||||
|
&& stack_.back() == qn("spreadsheetml", "row"))
|
||||||
|
{
|
||||||
|
// We're at the end of a row.
|
||||||
|
expect_end_element(qn("spreadsheetml", "row"));
|
||||||
|
// ... and keep parsing.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser().peek() == xml::parser::event_type::end_element
|
||||||
|
&& stack_.back() == qn("spreadsheetml", "sheetData"))
|
||||||
|
{
|
||||||
|
// End of sheet. Mark it by setting streaming_cell_ to nullptr, so we never get here again.
|
||||||
|
expect_end_element(qn("spreadsheetml", "sheetData"));
|
||||||
|
streaming_cell_.reset(nullptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_start_element(qn("spreadsheetml", "row"), xml::content::complex); // CT_Row
|
||||||
|
auto row_index = static_cast<row_t>(std::stoul(parser().attribute("r")));
|
||||||
|
auto &row_properties = ws.row_properties(row_index);
|
||||||
|
|
||||||
|
if (parser().attribute_present("ht"))
|
||||||
|
{
|
||||||
|
row_properties.height = converter_.deserialise(parser().attribute("ht"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser().attribute_present("customHeight"))
|
||||||
|
{
|
||||||
|
row_properties.custom_height = is_true(parser().attribute("customHeight"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser().attribute_present("hidden") && is_true(parser().attribute("hidden")))
|
||||||
|
{
|
||||||
|
row_properties.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser().attribute_present(qn("x14ac", "dyDescent")))
|
||||||
|
{
|
||||||
|
row_properties.dy_descent = converter_.deserialise(parser().attribute(qn("x14ac", "dyDescent")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser().attribute_present("spans"))
|
||||||
|
{
|
||||||
|
row_properties.spans = parser().attribute("spans");
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_attributes({"customFormat", "s", "customFont",
|
||||||
|
"outlineLevel", "collapsed", "thickTop", "thickBot",
|
||||||
|
"ph"});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!streaming_cell_)
|
||||||
|
{
|
||||||
|
// We're at the end of the worksheet
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_start_element(qn("spreadsheetml", "c"), xml::content::complex);
|
||||||
|
|
||||||
|
assert(streaming_);
|
||||||
|
auto cell = xlnt::cell(streaming_cell_.get());
|
||||||
|
auto reference = cell_reference(parser().attribute("r"));
|
||||||
|
cell.d_->parent_ = current_worksheet_;
|
||||||
|
cell.d_->column_ = reference.column_index();
|
||||||
|
cell.d_->row_ = reference.row();
|
||||||
|
|
||||||
|
if (parser().attribute_present("ph"))
|
||||||
|
{
|
||||||
|
cell.d_->phonetics_visible_ = parser().attribute<bool>("ph");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto has_type = parser().attribute_present("t");
|
||||||
|
auto type = has_type ? parser().attribute("t") : "n";
|
||||||
|
|
||||||
|
if (parser().attribute_present("s"))
|
||||||
|
{
|
||||||
|
cell.format(target_.format(static_cast<std::size_t>(std::stoull(parser().attribute("s")))));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto has_value = false;
|
||||||
|
auto value_string = std::string();
|
||||||
|
|
||||||
|
auto has_formula = false;
|
||||||
|
auto has_shared_formula = false;
|
||||||
|
auto formula_value_string = std::string();
|
||||||
|
|
||||||
|
while (in_element(qn("spreadsheetml", "c")))
|
||||||
|
{
|
||||||
|
auto current_element = expect_start_element(xml::content::mixed);
|
||||||
|
|
||||||
|
if (current_element == qn("spreadsheetml", "v")) // s:ST_Xstring
|
||||||
|
{
|
||||||
|
has_value = true;
|
||||||
|
value_string = read_text();
|
||||||
|
}
|
||||||
|
else if (current_element == qn("spreadsheetml", "f")) // CT_CellFormula
|
||||||
|
{
|
||||||
|
has_formula = true;
|
||||||
|
|
||||||
|
if (parser().attribute_present("t"))
|
||||||
|
{
|
||||||
|
has_shared_formula = parser().attribute("t") == "shared";
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_attributes({"aca", "ref", "dt2D", "dtr", "del1",
|
||||||
|
"del2", "r1", "r2", "ca", "si", "bx"});
|
||||||
|
|
||||||
|
formula_value_string = read_text();
|
||||||
|
}
|
||||||
|
else if (current_element == qn("spreadsheetml", "is")) // CT_Rst
|
||||||
|
{
|
||||||
|
expect_start_element(qn("spreadsheetml", "t"), xml::content::simple);
|
||||||
|
has_value = true;
|
||||||
|
value_string = read_text();
|
||||||
|
expect_end_element(qn("spreadsheetml", "t"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unexpected_element(current_element);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_end_element(current_element);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_end_element(qn("spreadsheetml", "c"));
|
||||||
|
|
||||||
|
if (has_formula && !has_shared_formula)
|
||||||
|
{
|
||||||
|
cell.formula(formula_value_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_value)
|
||||||
|
{
|
||||||
|
if (type == "str")
|
||||||
|
{
|
||||||
|
cell.d_->value_text_ = value_string;
|
||||||
|
cell.data_type(cell::type::formula_string);
|
||||||
|
}
|
||||||
|
else if (type == "inlineStr")
|
||||||
|
{
|
||||||
|
cell.d_->value_text_ = value_string;
|
||||||
|
cell.data_type(cell::type::inline_string);
|
||||||
|
}
|
||||||
|
else if (type == "s")
|
||||||
|
{
|
||||||
|
cell.d_->value_numeric_ = converter_.deserialise(value_string);
|
||||||
|
cell.data_type(cell::type::shared_string);
|
||||||
|
}
|
||||||
|
else if (type == "b") // boolean
|
||||||
|
{
|
||||||
|
cell.value(is_true(value_string));
|
||||||
|
}
|
||||||
|
else if (type == "n") // numeric
|
||||||
|
{
|
||||||
|
cell.value(converter_.deserialise(value_string));
|
||||||
|
}
|
||||||
|
else if (!value_string.empty() && value_string[0] == '#')
|
||||||
|
{
|
||||||
|
cell.error(value_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<relationship> xlsx_consumer::read_relationships(const path &part)
|
std::vector<relationship> xlsx_consumer::read_relationships(const path &part)
|
||||||
@ -1883,12 +1891,14 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
|
|||||||
expect_start_element(qn("spreadsheetml", "sheet"), xml::content::simple);
|
expect_start_element(qn("spreadsheetml", "sheet"), xml::content::simple);
|
||||||
|
|
||||||
auto title = parser().attribute("name");
|
auto title = parser().attribute("name");
|
||||||
skip_attribute("state");
|
|
||||||
|
|
||||||
sheet_title_index_map_[title] = index++;
|
sheet_title_index_map_[title] = index++;
|
||||||
sheet_title_id_map_[title] = parser().attribute<std::size_t>("sheetId");
|
sheet_title_id_map_[title] = parser().attribute<std::size_t>("sheetId");
|
||||||
target_.d_->sheet_title_rel_id_map_[title] = parser().attribute(qn("r", "id"));
|
target_.d_->sheet_title_rel_id_map_[title] = parser().attribute(qn("r", "id"));
|
||||||
|
|
||||||
|
bool hidden = parser().attribute<std::string>("state", "") == "hidden";
|
||||||
|
target_.d_->sheet_hidden_.push_back(hidden);
|
||||||
|
|
||||||
expect_end_element(qn("spreadsheetml", "sheet"));
|
expect_end_element(qn("spreadsheetml", "sheet"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2088,7 +2098,7 @@ void xlsx_consumer::read_shared_string_table()
|
|||||||
{
|
{
|
||||||
expect_start_element(qn("spreadsheetml", "si"), xml::content::complex);
|
expect_start_element(qn("spreadsheetml", "si"), xml::content::complex);
|
||||||
auto rt = read_rich_text(qn("spreadsheetml", "si"));
|
auto rt = read_rich_text(qn("spreadsheetml", "si"));
|
||||||
target_.add_shared_string(rt);
|
target_.add_shared_string(rt, true);
|
||||||
expect_end_element(qn("spreadsheetml", "si"));
|
expect_end_element(qn("spreadsheetml", "si"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2277,7 +2287,7 @@ void xlsx_consumer::read_stylesheet()
|
|||||||
else if (current_style_element == qn("spreadsheetml", "fonts"))
|
else if (current_style_element == qn("spreadsheetml", "fonts"))
|
||||||
{
|
{
|
||||||
auto &fonts = stylesheet.fonts;
|
auto &fonts = stylesheet.fonts;
|
||||||
auto count = parser().attribute<std::size_t>("count");
|
auto count = parser().attribute<std::size_t>("count", 0);
|
||||||
|
|
||||||
if (parser().attribute_present(qn("x14ac", "knownFonts")))
|
if (parser().attribute_present(qn("x14ac", "knownFonts")))
|
||||||
{
|
{
|
||||||
@ -2414,7 +2424,7 @@ void xlsx_consumer::read_stylesheet()
|
|||||||
|
|
||||||
if (count != stylesheet.fonts.size())
|
if (count != stylesheet.fonts.size())
|
||||||
{
|
{
|
||||||
throw xlnt::exception("counts don't match");
|
// throw xlnt::exception("counts don't match");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (current_style_element == qn("spreadsheetml", "numFmts"))
|
else if (current_style_element == qn("spreadsheetml", "numFmts"))
|
||||||
|
@ -413,8 +413,6 @@ private:
|
|||||||
|
|
||||||
std::unique_ptr<detail::cell_impl> streaming_cell_;
|
std::unique_ptr<detail::cell_impl> streaming_cell_;
|
||||||
|
|
||||||
detail::cell_impl *current_cell_;
|
|
||||||
|
|
||||||
detail::worksheet_impl *current_worksheet_;
|
detail::worksheet_impl *current_worksheet_;
|
||||||
number_serialiser converter_;
|
number_serialiser converter_;
|
||||||
};
|
};
|
||||||
|
@ -944,12 +944,12 @@ void xlsx_producer::write_shared_string_table(const relationship & /*rel*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
write_attribute("count", string_count);
|
write_attribute("count", string_count);
|
||||||
write_attribute("uniqueCount", source_.shared_strings_by_id().size());
|
write_attribute("uniqueCount", source_.shared_strings().size());
|
||||||
|
|
||||||
for (const auto &string : source_.shared_strings_by_id())
|
for (const auto &text : source_.shared_strings())
|
||||||
{
|
{
|
||||||
write_start_element(xmlns, "si");
|
write_start_element(xmlns, "si");
|
||||||
write_rich_text(xmlns, string.second);
|
write_rich_text(xmlns, text);
|
||||||
write_end_element(xmlns, "si");
|
write_end_element(xmlns, "si");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ xlnt::uri roundtrip(xml::parser &p, xml::serializer &s)
|
|||||||
}
|
}
|
||||||
for (auto &ele : attribs)
|
for (auto &ele : attribs)
|
||||||
{
|
{
|
||||||
s.attribute(ele.first.string(), ele.second.value);
|
s.attribute(ele.first, ele.second.value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ date date::today()
|
|||||||
|
|
||||||
int date::weekday() const
|
int date::weekday() const
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifndef _MSC_VER
|
||||||
std::tm tm{0, 0, 0, day, month - 1, year - 1900, 0, 0, 0, 0, nullptr};
|
std::tm tm{0, 0, 0, day, month - 1, year - 1900, 0, 0, 0, 0, nullptr};
|
||||||
#else
|
#else
|
||||||
std::tm tm{0, 0, 0, day, month - 1, year - 1900, 0, 0, 0};
|
std::tm tm{0, 0, 0, day, month - 1, year - 1900, 0, 0, 0};
|
||||||
|
@ -681,6 +681,11 @@ worksheet workbook::sheet_by_index(std::size_t index)
|
|||||||
|
|
||||||
const worksheet workbook::sheet_by_index(std::size_t index) const
|
const worksheet workbook::sheet_by_index(std::size_t index) const
|
||||||
{
|
{
|
||||||
|
if (index >= d_->worksheets_.size())
|
||||||
|
{
|
||||||
|
throw invalid_parameter();
|
||||||
|
}
|
||||||
|
|
||||||
auto iter = d_->worksheets_.begin();
|
auto iter = d_->worksheets_.begin();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < index; ++i, ++iter)
|
for (std::size_t i = 0; i < index; ++i, ++iter)
|
||||||
@ -716,6 +721,16 @@ const worksheet workbook::sheet_by_id(std::size_t id) const
|
|||||||
throw key_not_found();
|
throw key_not_found();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool workbook::sheet_hidden_by_index(std::size_t index) const
|
||||||
|
{
|
||||||
|
if (index >= d_->sheet_hidden_.size())
|
||||||
|
{
|
||||||
|
throw invalid_parameter();
|
||||||
|
}
|
||||||
|
|
||||||
|
return d_->sheet_hidden_.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
worksheet workbook::active_sheet()
|
worksheet workbook::active_sheet()
|
||||||
{
|
{
|
||||||
return sheet_by_index(d_->active_sheet_index_.is_set() ? d_->active_sheet_index_.get() : 0);
|
return sheet_by_index(d_->active_sheet_index_.is_set() ? d_->active_sheet_index_.get() : 0);
|
||||||
@ -1348,32 +1363,25 @@ const manifest &workbook::manifest() const
|
|||||||
return d_->manifest_;
|
return d_->manifest_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<std::size_t, rich_text> &workbook::shared_strings_by_id() const
|
|
||||||
{
|
|
||||||
return d_->shared_strings_values_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rich_text &workbook::shared_strings(std::size_t index) const
|
const rich_text &workbook::shared_strings(std::size_t index) const
|
||||||
{
|
{
|
||||||
auto it = d_->shared_strings_values_.find(index);
|
if (index < d_->shared_strings_values_.size())
|
||||||
|
|
||||||
if (it != d_->shared_strings_values_.end())
|
|
||||||
{
|
{
|
||||||
return it->second;
|
return d_->shared_strings_values_.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static rich_text empty;
|
static rich_text empty;
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<rich_text, std::size_t, rich_text_hash> &workbook::shared_strings()
|
std::vector<rich_text> &workbook::shared_strings()
|
||||||
{
|
{
|
||||||
return d_->shared_strings_ids_;
|
return d_->shared_strings_values_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::unordered_map<rich_text, std::size_t, rich_text_hash> &workbook::shared_strings() const
|
const std::vector<rich_text> &workbook::shared_strings() const
|
||||||
{
|
{
|
||||||
return d_->shared_strings_ids_;
|
return d_->shared_strings_values_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t workbook::add_shared_string(const rich_text &shared, bool allow_duplicates)
|
std::size_t workbook::add_shared_string(const rich_text &shared, bool allow_duplicates)
|
||||||
@ -1392,7 +1400,7 @@ std::size_t workbook::add_shared_string(const rich_text &shared, bool allow_dupl
|
|||||||
|
|
||||||
auto sz = d_->shared_strings_ids_.size();
|
auto sz = d_->shared_strings_ids_.size();
|
||||||
d_->shared_strings_ids_[shared] = sz;
|
d_->shared_strings_ids_[shared] = sz;
|
||||||
d_->shared_strings_values_[sz] = shared;
|
d_->shared_strings_values_.push_back(shared);
|
||||||
|
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,15 @@ range_reference::range_reference(const char *range_string)
|
|||||||
range_reference::range_reference(const std::string &range_string)
|
range_reference::range_reference(const std::string &range_string)
|
||||||
: top_left_("A1"), bottom_right_("A1")
|
: top_left_("A1"), bottom_right_("A1")
|
||||||
{
|
{
|
||||||
auto colon_index = range_string.find(':');
|
auto colon_index = range_string.find(' ');
|
||||||
|
|
||||||
|
if (colon_index != std::string::npos)
|
||||||
|
{
|
||||||
|
// Multiple cell selection is not supported at this time.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
colon_index = range_string.find(':');
|
||||||
|
|
||||||
if (colon_index != std::string::npos)
|
if (colon_index != std::string::npos)
|
||||||
{
|
{
|
||||||
|
@ -1335,4 +1335,9 @@ bool worksheet::has_drawing() const
|
|||||||
return d_->drawing_.is_set();
|
return d_->drawing_.is_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool worksheet::is_empty() const
|
||||||
|
{
|
||||||
|
return d_->cell_map_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
BIN
tests/data/16_hidden_sheet.xlsx
Normal file
BIN
tests/data/16_hidden_sheet.xlsx
Normal file
Binary file not shown.
BIN
tests/data/Issue492_empty_row.xlsx
Normal file
BIN
tests/data/Issue492_empty_row.xlsx
Normal file
Binary file not shown.
BIN
tests/data/Issue494_shared_string.xlsx
Executable file
BIN
tests/data/Issue494_shared_string.xlsx
Executable file
Binary file not shown.
BIN
tests/data/Issue503_external_link.xlsx
Executable file
BIN
tests/data/Issue503_external_link.xlsx
Executable file
Binary file not shown.
@ -23,28 +23,28 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <xlnt/cell/cell.hpp>
|
||||||
#include <xlnt/cell/comment.hpp>
|
#include <xlnt/cell/comment.hpp>
|
||||||
#include <xlnt/cell/hyperlink.hpp>
|
#include <xlnt/cell/hyperlink.hpp>
|
||||||
#include <xlnt/cell/cell.hpp>
|
#include <xlnt/styles/border.hpp>
|
||||||
#include <xlnt/styles/font.hpp>
|
|
||||||
#include <xlnt/styles/style.hpp>
|
|
||||||
#include <xlnt/styles/fill.hpp>
|
#include <xlnt/styles/fill.hpp>
|
||||||
|
#include <xlnt/styles/font.hpp>
|
||||||
#include <xlnt/styles/format.hpp>
|
#include <xlnt/styles/format.hpp>
|
||||||
#include <xlnt/styles/number_format.hpp>
|
#include <xlnt/styles/number_format.hpp>
|
||||||
#include <xlnt/styles/border.hpp>
|
#include <xlnt/styles/style.hpp>
|
||||||
#include <xlnt/utils/date.hpp>
|
#include <xlnt/utils/date.hpp>
|
||||||
#include <xlnt/utils/datetime.hpp>
|
#include <xlnt/utils/datetime.hpp>
|
||||||
#include <xlnt/utils/time.hpp>
|
#include <xlnt/utils/time.hpp>
|
||||||
#include <xlnt/utils/timedelta.hpp>
|
#include <xlnt/utils/timedelta.hpp>
|
||||||
#include <xlnt/utils/variant.hpp>
|
#include <xlnt/utils/variant.hpp>
|
||||||
|
#include <xlnt/workbook/metadata_property.hpp>
|
||||||
#include <xlnt/workbook/streaming_workbook_reader.hpp>
|
#include <xlnt/workbook/streaming_workbook_reader.hpp>
|
||||||
#include <xlnt/workbook/streaming_workbook_writer.hpp>
|
#include <xlnt/workbook/streaming_workbook_writer.hpp>
|
||||||
#include <xlnt/workbook/workbook.hpp>
|
#include <xlnt/workbook/workbook.hpp>
|
||||||
#include <xlnt/workbook/metadata_property.hpp>
|
|
||||||
#include <xlnt/worksheet/column_properties.hpp>
|
#include <xlnt/worksheet/column_properties.hpp>
|
||||||
|
#include <xlnt/worksheet/header_footer.hpp>
|
||||||
#include <xlnt/worksheet/row_properties.hpp>
|
#include <xlnt/worksheet/row_properties.hpp>
|
||||||
#include <xlnt/worksheet/sheet_format_properties.hpp>
|
#include <xlnt/worksheet/sheet_format_properties.hpp>
|
||||||
#include <xlnt/worksheet/header_footer.hpp>
|
|
||||||
#include <xlnt/worksheet/worksheet.hpp>
|
#include <xlnt/worksheet/worksheet.hpp>
|
||||||
#include <detail/cryptography/xlsx_crypto_consumer.hpp>
|
#include <detail/cryptography/xlsx_crypto_consumer.hpp>
|
||||||
#include <detail/serialization/vector_streambuf.hpp>
|
#include <detail/serialization/vector_streambuf.hpp>
|
||||||
@ -93,6 +93,8 @@ public:
|
|||||||
register_test(test_load_save_german_locale);
|
register_test(test_load_save_german_locale);
|
||||||
register_test(test_Issue445_inline_str_load);
|
register_test(test_Issue445_inline_str_load);
|
||||||
register_test(test_Issue445_inline_str_streaming_read);
|
register_test(test_Issue445_inline_str_streaming_read);
|
||||||
|
register_test(test_Issue492_stream_empty_row);
|
||||||
|
register_test(test_Issue503_external_link_load);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool workbook_matches_file(xlnt::workbook &wb, const xlnt::path &file)
|
bool workbook_matches_file(xlnt::workbook &wb, const xlnt::path &file)
|
||||||
@ -714,7 +716,7 @@ public:
|
|||||||
|
|
||||||
void test_load_save_german_locale()
|
void test_load_save_german_locale()
|
||||||
{
|
{
|
||||||
/* std::locale current(std::locale::global(std::locale("de-DE")));
|
/* std::locale current(std::locale::global(std::locale("de-DE")));
|
||||||
test_round_trip_rw_custom_heights_widths();
|
test_round_trip_rw_custom_heights_widths();
|
||||||
std::locale::global(current);*/
|
std::locale::global(current);*/
|
||||||
}
|
}
|
||||||
@ -733,8 +735,35 @@ public:
|
|||||||
xlnt::streaming_workbook_reader wbr;
|
xlnt::streaming_workbook_reader wbr;
|
||||||
wbr.open(path_helper::test_file("Issue445_inline_str.xlsx"));
|
wbr.open(path_helper::test_file("Issue445_inline_str.xlsx"));
|
||||||
wbr.begin_worksheet("Sheet");
|
wbr.begin_worksheet("Sheet");
|
||||||
|
xlnt_assert(wbr.has_cell());
|
||||||
auto cell = wbr.read_cell();
|
auto cell = wbr.read_cell();
|
||||||
xlnt_assert_equals(cell.value<std::string>(), std::string("a"));
|
xlnt_assert_equals(cell.value<std::string>(), std::string("a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_Issue492_stream_empty_row()
|
||||||
|
{
|
||||||
|
xlnt::streaming_workbook_reader wbr;
|
||||||
|
wbr.open(path_helper::test_file("Issue492_empty_row.xlsx"));
|
||||||
|
wbr.begin_worksheet("BLS Data Series");
|
||||||
|
xlnt_assert(wbr.has_cell());
|
||||||
|
xlnt_assert_equals(wbr.read_cell().reference(), "A1");
|
||||||
|
xlnt_assert(wbr.has_cell());
|
||||||
|
xlnt_assert_equals(wbr.read_cell().reference(), "A2");
|
||||||
|
xlnt_assert(wbr.has_cell());
|
||||||
|
xlnt_assert_equals(wbr.read_cell().reference(), "A4");
|
||||||
|
xlnt_assert(wbr.has_cell());
|
||||||
|
xlnt_assert_equals(wbr.read_cell().reference(), "B4");
|
||||||
|
xlnt_assert(!wbr.has_cell());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_Issue503_external_link_load()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
wb.load(path_helper::test_file("Issue503_external_link.xlsx"));
|
||||||
|
auto ws = wb.active_sheet();
|
||||||
|
auto cell = ws.cell("A1");
|
||||||
|
xlnt_assert_equals(cell.value<std::string>(), std::string("WDG_IC_00000003.aut"));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static serialization_test_suite x;
|
static serialization_test_suite x;
|
||||||
|
@ -49,6 +49,8 @@ public:
|
|||||||
register_test(test_add_sheet_at_index);
|
register_test(test_add_sheet_at_index);
|
||||||
register_test(test_get_sheet_by_title);
|
register_test(test_get_sheet_by_title);
|
||||||
register_test(test_get_sheet_by_title_const);
|
register_test(test_get_sheet_by_title_const);
|
||||||
|
register_test(test_get_sheet_by_index);
|
||||||
|
register_test(test_get_sheet_by_index_const);
|
||||||
register_test(test_index_operator);
|
register_test(test_index_operator);
|
||||||
register_test(test_contains);
|
register_test(test_contains);
|
||||||
register_test(test_iter);
|
register_test(test_iter);
|
||||||
@ -68,6 +70,7 @@ public:
|
|||||||
register_test(test_load_file);
|
register_test(test_load_file);
|
||||||
register_test(test_Issue279);
|
register_test(test_Issue279);
|
||||||
register_test(test_Issue353);
|
register_test(test_Issue353);
|
||||||
|
register_test(test_Issue494);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_active_sheet()
|
void test_active_sheet()
|
||||||
@ -151,6 +154,23 @@ public:
|
|||||||
xlnt_assert_equals(new_sheet, found_sheet);
|
xlnt_assert_equals(new_sheet, found_sheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_get_sheet_by_index()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
auto new_sheet = wb.create_sheet();
|
||||||
|
xlnt_assert_equals(new_sheet, wb.sheet_by_index(1)); // in range
|
||||||
|
xlnt_assert_throws(wb.sheet_by_index(2), xlnt::invalid_parameter); // out of range
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_get_sheet_by_index_const()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
auto new_sheet = wb.create_sheet();
|
||||||
|
const auto &wb_const = wb;
|
||||||
|
xlnt_assert_equals(new_sheet, wb_const.sheet_by_index(1)); // in range
|
||||||
|
xlnt_assert_throws(wb_const.sheet_by_index(2), xlnt::invalid_parameter); // out of range
|
||||||
|
}
|
||||||
|
|
||||||
void test_index_operator() // test_getitem
|
void test_index_operator() // test_getitem
|
||||||
{
|
{
|
||||||
xlnt::workbook wb;
|
xlnt::workbook wb;
|
||||||
@ -509,5 +529,14 @@ public:
|
|||||||
xlnt_assert_equals(ws.row_properties(1).spans.get(), "1:8");
|
xlnt_assert_equals(ws.row_properties(1).spans.get(), "1:8");
|
||||||
xlnt_assert_equals(ws.row_properties(17).spans.get(), "2:7");
|
xlnt_assert_equals(ws.row_properties(17).spans.get(), "2:7");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_Issue494()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
wb.load(path_helper::test_file("Issue494_shared_string.xlsx"));
|
||||||
|
auto ws = wb.active_sheet();
|
||||||
|
xlnt_assert_equals(ws.cell(2, 1).to_string(), "V1.00");
|
||||||
|
xlnt_assert_equals(ws.cell(2, 2).to_string(), "V1.00");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
static workbook_test_suite x;
|
static workbook_test_suite x;
|
||||||
|
@ -112,6 +112,7 @@ public:
|
|||||||
register_test(test_delete_columns);
|
register_test(test_delete_columns);
|
||||||
register_test(test_insert_too_many);
|
register_test(test_insert_too_many);
|
||||||
register_test(test_insert_delete_moves_merges);
|
register_test(test_insert_delete_moves_merges);
|
||||||
|
register_test(test_hidden_sheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_new_worksheet()
|
void test_new_worksheet()
|
||||||
@ -1582,5 +1583,12 @@ public:
|
|||||||
xlnt_assert_equals(merged, expected);
|
xlnt_assert_equals(merged, expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_hidden_sheet()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
wb.load(path_helper::test_file("16_hidden_sheet.xlsx"));
|
||||||
|
xlnt_assert_equals(wb.sheet_hidden_by_index(1), true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
static worksheet_test_suite x;
|
static worksheet_test_suite x;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user