mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
Merge branch 'master' into time-struct-warning
This commit is contained in:
commit
b6d566f1f7
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
|
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 |
|
@ -21,6 +21,7 @@
|
|||
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||
// @author: see AUTHORS file
|
||||
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <numeric> // for std::accumulate
|
||||
#include <sstream>
|
||||
|
@ -406,171 +407,7 @@ void xlsx_consumer::open(std::istream &source)
|
|||
|
||||
cell xlsx_consumer::read_cell()
|
||||
{
|
||||
if (!has_cell())
|
||||
{
|
||||
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;
|
||||
return cell(streaming_cell_.get());
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
||||
|
@ -1411,8 +1248,174 @@ xml::parser &xlsx_consumer::parser()
|
|||
|
||||
bool xlsx_consumer::has_cell()
|
||||
{
|
||||
return in_element(qn("spreadsheetml", "row"))
|
||||
|| in_element(qn("spreadsheetml", "sheetData"));
|
||||
auto ws = worksheet(current_worksheet_);
|
||||
|
||||
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)
|
||||
|
|
|
@ -413,8 +413,6 @@ private:
|
|||
|
||||
std::unique_ptr<detail::cell_impl> streaming_cell_;
|
||||
|
||||
detail::cell_impl *current_cell_;
|
||||
|
||||
detail::worksheet_impl *current_worksheet_;
|
||||
number_serialiser converter_;
|
||||
};
|
||||
|
|
BIN
tests/data/Issue492_empty_row.xlsx
Normal file
BIN
tests/data/Issue492_empty_row.xlsx
Normal file
Binary file not shown.
|
@ -93,6 +93,7 @@ public:
|
|||
register_test(test_load_save_german_locale);
|
||||
register_test(test_Issue445_inline_str_load);
|
||||
register_test(test_Issue445_inline_str_streaming_read);
|
||||
register_test(test_Issue492_stream_empty_row);
|
||||
}
|
||||
|
||||
bool workbook_matches_file(xlnt::workbook &wb, const xlnt::path &file)
|
||||
|
@ -733,8 +734,25 @@ public:
|
|||
xlnt::streaming_workbook_reader wbr;
|
||||
wbr.open(path_helper::test_file("Issue445_inline_str.xlsx"));
|
||||
wbr.begin_worksheet("Sheet");
|
||||
xlnt_assert(wbr.has_cell());
|
||||
auto cell = wbr.read_cell();
|
||||
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());
|
||||
}
|
||||
};
|
||||
static serialization_test_suite x;
|
||||
|
|
Loading…
Reference in New Issue
Block a user