python-calamine 0.3.2__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_calamine-0.3.2 → python_calamine-0.4.0}/Cargo.lock +15 -16
- {python_calamine-0.3.2 → python_calamine-0.4.0}/Cargo.toml +4 -4
- {python_calamine-0.3.2 → python_calamine-0.4.0}/PKG-INFO +1 -1
- {python_calamine-0.3.2 → python_calamine-0.4.0}/python/python_calamine/_python_calamine.pyi +12 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/src/types/sheet.rs +19 -4
- {python_calamine-0.3.2 → python_calamine-0.4.0}/src/types/workbook.rs +40 -4
- python_calamine-0.4.0/tests/data/base.ods +0 -0
- python_calamine-0.4.0/tests/data/base.xls +0 -0
- python_calamine-0.4.0/tests/data/base.xlsb +0 -0
- python_calamine-0.4.0/tests/data/base.xlsx +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/test_base.py +17 -5
- python_calamine-0.3.2/tests/data/base.ods +0 -0
- python_calamine-0.3.2/tests/data/base.xls +0 -0
- python_calamine-0.3.2/tests/data/base.xlsb +0 -0
- python_calamine-0.3.2/tests/data/base.xlsx +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/.github/workflows/CI.yml +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/.gitignore +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/.pre-commit-config.yaml +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/LICENSE +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/README.md +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/build.rs +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/pyproject.toml +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/python/python_calamine/__init__.py +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/python/python_calamine/pandas.py +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/python/python_calamine/py.typed +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/renovate.json +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/src/lib.rs +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/src/types/cell.rs +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/src/types/errors.rs +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/src/types/mod.rs +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/src/utils.rs +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/__init__.py +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/conftest.py +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/any_sheets.ods +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/any_sheets.xls +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/any_sheets.xlsb +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/any_sheets.xlsx +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/empty_file.ods +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/empty_file.xlsb +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/empty_file.xlsx +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/password.ods +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/password.xls +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/password.xlsb +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/data/password.xlsx +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/test_pandas.py +0 -0
- {python_calamine-0.3.2 → python_calamine-0.4.0}/tests/test_sheet_type.py +0 -0
|
@@ -133,9 +133,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
|
133
133
|
|
|
134
134
|
[[package]]
|
|
135
135
|
name = "chrono"
|
|
136
|
-
version = "0.4.
|
|
136
|
+
version = "0.4.41"
|
|
137
137
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
138
|
-
checksum = "
|
|
138
|
+
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
|
139
139
|
dependencies = [
|
|
140
140
|
"android-tzdata",
|
|
141
141
|
"iana-time-zone",
|
|
@@ -429,11 +429,10 @@ dependencies = [
|
|
|
429
429
|
|
|
430
430
|
[[package]]
|
|
431
431
|
name = "pyo3"
|
|
432
|
-
version = "0.
|
|
432
|
+
version = "0.25.1"
|
|
433
433
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
434
|
-
checksum = "
|
|
434
|
+
checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a"
|
|
435
435
|
dependencies = [
|
|
436
|
-
"cfg-if",
|
|
437
436
|
"chrono",
|
|
438
437
|
"indoc",
|
|
439
438
|
"libc",
|
|
@@ -448,9 +447,9 @@ dependencies = [
|
|
|
448
447
|
|
|
449
448
|
[[package]]
|
|
450
449
|
name = "pyo3-build-config"
|
|
451
|
-
version = "0.
|
|
450
|
+
version = "0.25.1"
|
|
452
451
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
453
|
-
checksum = "
|
|
452
|
+
checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598"
|
|
454
453
|
dependencies = [
|
|
455
454
|
"once_cell",
|
|
456
455
|
"python3-dll-a",
|
|
@@ -459,9 +458,9 @@ dependencies = [
|
|
|
459
458
|
|
|
460
459
|
[[package]]
|
|
461
460
|
name = "pyo3-ffi"
|
|
462
|
-
version = "0.
|
|
461
|
+
version = "0.25.1"
|
|
463
462
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
464
|
-
checksum = "
|
|
463
|
+
checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c"
|
|
465
464
|
dependencies = [
|
|
466
465
|
"libc",
|
|
467
466
|
"pyo3-build-config",
|
|
@@ -469,9 +468,9 @@ dependencies = [
|
|
|
469
468
|
|
|
470
469
|
[[package]]
|
|
471
470
|
name = "pyo3-file"
|
|
472
|
-
version = "0.
|
|
471
|
+
version = "0.13.0"
|
|
473
472
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
474
|
-
checksum = "
|
|
473
|
+
checksum = "75916300df50dbfa6958ec05fe53473e69474542dac7fd1275aa6869a18a241a"
|
|
475
474
|
dependencies = [
|
|
476
475
|
"pyo3",
|
|
477
476
|
"skeptic",
|
|
@@ -479,9 +478,9 @@ dependencies = [
|
|
|
479
478
|
|
|
480
479
|
[[package]]
|
|
481
480
|
name = "pyo3-macros"
|
|
482
|
-
version = "0.
|
|
481
|
+
version = "0.25.1"
|
|
483
482
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
484
|
-
checksum = "
|
|
483
|
+
checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50"
|
|
485
484
|
dependencies = [
|
|
486
485
|
"proc-macro2",
|
|
487
486
|
"pyo3-macros-backend",
|
|
@@ -491,9 +490,9 @@ dependencies = [
|
|
|
491
490
|
|
|
492
491
|
[[package]]
|
|
493
492
|
name = "pyo3-macros-backend"
|
|
494
|
-
version = "0.
|
|
493
|
+
version = "0.25.1"
|
|
495
494
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
496
|
-
checksum = "
|
|
495
|
+
checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc"
|
|
497
496
|
dependencies = [
|
|
498
497
|
"heck",
|
|
499
498
|
"proc-macro2",
|
|
@@ -504,7 +503,7 @@ dependencies = [
|
|
|
504
503
|
|
|
505
504
|
[[package]]
|
|
506
505
|
name = "python-calamine"
|
|
507
|
-
version = "0.
|
|
506
|
+
version = "0.4.0"
|
|
508
507
|
dependencies = [
|
|
509
508
|
"calamine",
|
|
510
509
|
"chrono",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "python-calamine"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.0"
|
|
4
4
|
authors = ["Dmitriy <dimastbk@proton.me>"]
|
|
5
5
|
description = "Python binding for Rust's library for reading excel and odf file - calamine"
|
|
6
6
|
edition = "2021"
|
|
@@ -15,13 +15,13 @@ crate-type = ["cdylib"]
|
|
|
15
15
|
|
|
16
16
|
[dependencies]
|
|
17
17
|
calamine = { git = "https://github.com/tafia/calamine.git", rev = "5cda5c734661f656bdfb7ac7a1b95e77bf89aa09", features = ["dates"] }
|
|
18
|
-
pyo3 = { version = "0.
|
|
18
|
+
pyo3 = { version = "0.25.1", features = [
|
|
19
19
|
"extension-module",
|
|
20
20
|
"chrono",
|
|
21
21
|
"generate-import-lib",
|
|
22
22
|
] }
|
|
23
23
|
chrono = { version = "0.4.38", features = ["serde"] }
|
|
24
|
-
pyo3-file = "0.
|
|
24
|
+
pyo3-file = "0.13.0"
|
|
25
25
|
|
|
26
26
|
[build-dependencies]
|
|
27
|
-
pyo3-build-config = "0.
|
|
27
|
+
pyo3-build-config = "0.25.1"
|
|
@@ -89,6 +89,18 @@ class CalamineSheet:
|
|
|
89
89
|
]:
|
|
90
90
|
"""Retunrning data from sheet as iterator of lists."""
|
|
91
91
|
|
|
92
|
+
@property
|
|
93
|
+
def merged_cell_ranges(
|
|
94
|
+
self,
|
|
95
|
+
) -> list[tuple[tuple[int, int], tuple[int, int]]] | None:
|
|
96
|
+
"""Return a copy of merged cell ranges.
|
|
97
|
+
|
|
98
|
+
Support only for xlsx/xls.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
list of merged cell ranges (tuple[start coordinate, end coordinate]) or None for unsuported format
|
|
102
|
+
"""
|
|
103
|
+
|
|
92
104
|
@typing.final
|
|
93
105
|
class CalamineWorkbook(contextlib.AbstractContextManager):
|
|
94
106
|
path: str | None
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use std::fmt::Display;
|
|
2
2
|
use std::sync::Arc;
|
|
3
3
|
|
|
4
|
-
use calamine::{Data, Range, Rows, SheetType, SheetVisible};
|
|
4
|
+
use calamine::{Data, Dimensions, Range, Rows, SheetType, SheetVisible};
|
|
5
5
|
use pyo3::class::basic::CompareOp;
|
|
6
6
|
use pyo3::prelude::*;
|
|
7
7
|
use pyo3::types::PyList;
|
|
@@ -25,7 +25,7 @@ pub enum SheetTypeEnum {
|
|
|
25
25
|
|
|
26
26
|
impl Display for SheetTypeEnum {
|
|
27
27
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
28
|
-
write!(f, "SheetTypeEnum.{:?}"
|
|
28
|
+
write!(f, "SheetTypeEnum.{self:?}")
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -54,7 +54,7 @@ pub enum SheetVisibleEnum {
|
|
|
54
54
|
|
|
55
55
|
impl Display for SheetVisibleEnum {
|
|
56
56
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
57
|
-
write!(f, "SheetVisibleEnum.{:?}"
|
|
57
|
+
write!(f, "SheetVisibleEnum.{self:?}")
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -68,6 +68,8 @@ impl From<SheetVisible> for SheetVisibleEnum {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
type MergedCellRange = ((u32, u32), (u32, u32));
|
|
72
|
+
|
|
71
73
|
#[pyclass]
|
|
72
74
|
#[derive(Clone, PartialEq)]
|
|
73
75
|
pub struct SheetMetadata {
|
|
@@ -132,13 +134,19 @@ pub struct CalamineSheet {
|
|
|
132
134
|
#[pyo3(get)]
|
|
133
135
|
name: String,
|
|
134
136
|
range: Arc<Range<Data>>,
|
|
137
|
+
merged_cell_ranges: Option<Vec<Dimensions>>,
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
impl CalamineSheet {
|
|
138
|
-
pub fn new(
|
|
141
|
+
pub fn new(
|
|
142
|
+
name: String,
|
|
143
|
+
range: Range<Data>,
|
|
144
|
+
merged_cell_ranges: Option<Vec<Dimensions>>,
|
|
145
|
+
) -> Self {
|
|
139
146
|
CalamineSheet {
|
|
140
147
|
name,
|
|
141
148
|
range: Arc::new(range),
|
|
149
|
+
merged_cell_ranges,
|
|
142
150
|
}
|
|
143
151
|
}
|
|
144
152
|
}
|
|
@@ -212,6 +220,13 @@ impl CalamineSheet {
|
|
|
212
220
|
fn iter_rows(&self) -> CalamineCellIterator {
|
|
213
221
|
CalamineCellIterator::from_range(Arc::clone(&self.range))
|
|
214
222
|
}
|
|
223
|
+
|
|
224
|
+
#[getter]
|
|
225
|
+
fn merged_cell_ranges(slf: PyRef<'_, Self>) -> Option<Vec<MergedCellRange>> {
|
|
226
|
+
slf.merged_cell_ranges
|
|
227
|
+
.as_ref()
|
|
228
|
+
.map(|r| r.iter().map(|d| (d.start, d.end)).collect())
|
|
229
|
+
}
|
|
215
230
|
}
|
|
216
231
|
|
|
217
232
|
#[pyclass]
|
|
@@ -2,7 +2,9 @@ use std::fs::File;
|
|
|
2
2
|
use std::io::{BufReader, Cursor, Read};
|
|
3
3
|
use std::path::PathBuf;
|
|
4
4
|
|
|
5
|
-
use calamine::{
|
|
5
|
+
use calamine::{
|
|
6
|
+
open_workbook_auto, open_workbook_auto_from_rs, Error as CalamineCrateError, Reader, Sheets,
|
|
7
|
+
};
|
|
6
8
|
use pyo3::exceptions::PyTypeError;
|
|
7
9
|
use pyo3::prelude::*;
|
|
8
10
|
use pyo3::types::{PyString, PyType};
|
|
@@ -44,6 +46,35 @@ impl SheetsEnum {
|
|
|
44
46
|
SheetsEnum::None => Err(Error::WorkbookClosed),
|
|
45
47
|
}
|
|
46
48
|
}
|
|
49
|
+
|
|
50
|
+
fn worksheet_merge_cells(
|
|
51
|
+
&mut self,
|
|
52
|
+
name: &str,
|
|
53
|
+
) -> Result<Option<Vec<calamine::Dimensions>>, Error> {
|
|
54
|
+
match self {
|
|
55
|
+
SheetsEnum::File(f) => match f {
|
|
56
|
+
Sheets::Xls(xls_f) => Ok(xls_f.worksheet_merge_cells(name)),
|
|
57
|
+
Sheets::Xlsx(xlsx_f) => xlsx_f
|
|
58
|
+
.worksheet_merge_cells(name)
|
|
59
|
+
.transpose()
|
|
60
|
+
.map_err(CalamineCrateError::Xlsx)
|
|
61
|
+
.map_err(Error::Calamine)
|
|
62
|
+
.map(|inner| inner.or(Some(Vec::new()))),
|
|
63
|
+
_ => Ok(None),
|
|
64
|
+
},
|
|
65
|
+
SheetsEnum::FileLike(f) => match f {
|
|
66
|
+
Sheets::Xls(xls_f) => Ok(xls_f.worksheet_merge_cells(name)),
|
|
67
|
+
Sheets::Xlsx(xlsx_f) => xlsx_f
|
|
68
|
+
.worksheet_merge_cells(name)
|
|
69
|
+
.transpose()
|
|
70
|
+
.map_err(CalamineCrateError::Xlsx)
|
|
71
|
+
.map_err(Error::Calamine)
|
|
72
|
+
.map(|inner| inner.or(Some(Vec::new()))),
|
|
73
|
+
_ => Ok(None),
|
|
74
|
+
},
|
|
75
|
+
SheetsEnum::None => Err(Error::WorkbookClosed),
|
|
76
|
+
}
|
|
77
|
+
}
|
|
47
78
|
}
|
|
48
79
|
|
|
49
80
|
#[pyclass]
|
|
@@ -61,7 +92,7 @@ pub struct CalamineWorkbook {
|
|
|
61
92
|
impl CalamineWorkbook {
|
|
62
93
|
fn __repr__(&self) -> PyResult<String> {
|
|
63
94
|
match &self.path {
|
|
64
|
-
Some(path) => Ok(format!("CalamineWorkbook(path='{}')"
|
|
95
|
+
Some(path) => Ok(format!("CalamineWorkbook(path='{path}')")),
|
|
65
96
|
None => Ok("CalamineWorkbook(path='bytes')".to_string()),
|
|
66
97
|
}
|
|
67
98
|
}
|
|
@@ -192,14 +223,19 @@ impl CalamineWorkbook {
|
|
|
192
223
|
|
|
193
224
|
fn get_sheet_by_name(&mut self, name: &str) -> PyResult<CalamineSheet> {
|
|
194
225
|
let range = self.sheets.worksheet_range(name).map_err(err_to_py)?;
|
|
195
|
-
|
|
226
|
+
let merge_cells_range = self.sheets.worksheet_merge_cells(name).map_err(err_to_py)?;
|
|
227
|
+
Ok(CalamineSheet::new(
|
|
228
|
+
name.to_owned(),
|
|
229
|
+
range,
|
|
230
|
+
merge_cells_range,
|
|
231
|
+
))
|
|
196
232
|
}
|
|
197
233
|
|
|
198
234
|
fn get_sheet_by_index(&mut self, index: usize) -> PyResult<CalamineSheet> {
|
|
199
235
|
let name = self
|
|
200
236
|
.sheet_names
|
|
201
237
|
.get(index)
|
|
202
|
-
.ok_or_else(|| WorksheetNotFound::new_err(format!("Worksheet '{}' not found"
|
|
238
|
+
.ok_or_else(|| WorksheetNotFound::new_err(format!("Worksheet '{index}' not found")))?
|
|
203
239
|
.to_string();
|
|
204
240
|
self.get_sheet_by_name(&name)
|
|
205
241
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -15,7 +15,7 @@ PATH = Path(__file__).parent / "data"
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def test_ods_read():
|
|
18
|
-
names = ["Sheet1", "Sheet2"]
|
|
18
|
+
names = ["Sheet1", "Sheet2", "Merged Cells"]
|
|
19
19
|
data = [
|
|
20
20
|
["", "", "", "", "", "", "", "", "", ""],
|
|
21
21
|
[
|
|
@@ -59,9 +59,11 @@ def test_ods_read():
|
|
|
59
59
|
assert [] == reader.get_sheet_by_index(1).to_python()
|
|
60
60
|
assert [] == reader.get_sheet_by_index(1).to_python(skip_empty_area=False)
|
|
61
61
|
|
|
62
|
+
assert None is reader.get_sheet_by_name("Merged Cells").merged_cell_ranges
|
|
63
|
+
|
|
62
64
|
|
|
63
65
|
def test_xls_read():
|
|
64
|
-
names = ["Sheet1", "Sheet2"]
|
|
66
|
+
names = ["Sheet1", "Sheet2", "Merged Cells"]
|
|
65
67
|
data = [
|
|
66
68
|
["", "", "", "", "", "", "", "", "", ""],
|
|
67
69
|
[
|
|
@@ -101,9 +103,13 @@ def test_xls_read():
|
|
|
101
103
|
assert [] == reader.get_sheet_by_index(1).to_python()
|
|
102
104
|
assert [] == reader.get_sheet_by_index(1).to_python(skip_empty_area=False)
|
|
103
105
|
|
|
106
|
+
assert [((0, 0), (1, 0)), ((0, 1), (1, 1))] == reader.get_sheet_by_name(
|
|
107
|
+
"Merged Cells"
|
|
108
|
+
).merged_cell_ranges
|
|
109
|
+
|
|
104
110
|
|
|
105
111
|
def test_xlsb_read():
|
|
106
|
-
names = ["Sheet1", "Sheet2", "Sheet3"]
|
|
112
|
+
names = ["Sheet1", "Sheet2", "Sheet3", "Merged Cells"]
|
|
107
113
|
data = [
|
|
108
114
|
["", "", "", "", "", "", "", "", "", ""],
|
|
109
115
|
[
|
|
@@ -143,9 +149,11 @@ def test_xlsb_read():
|
|
|
143
149
|
assert [] == reader.get_sheet_by_index(1).to_python()
|
|
144
150
|
assert [] == reader.get_sheet_by_index(1).to_python(skip_empty_area=False)
|
|
145
151
|
|
|
152
|
+
assert None is reader.get_sheet_by_name("Merged Cells").merged_cell_ranges
|
|
153
|
+
|
|
146
154
|
|
|
147
155
|
def test_xlsx_read():
|
|
148
|
-
names = ["Sheet1", "Sheet2", "Sheet3"]
|
|
156
|
+
names = ["Sheet1", "Sheet2", "Sheet3", "Merged Cells"]
|
|
149
157
|
data = [
|
|
150
158
|
["", "", "", "", "", "", "", "", "", ""],
|
|
151
159
|
[
|
|
@@ -185,9 +193,13 @@ def test_xlsx_read():
|
|
|
185
193
|
assert [] == reader.get_sheet_by_index(1).to_python()
|
|
186
194
|
assert [] == reader.get_sheet_by_index(1).to_python(skip_empty_area=False)
|
|
187
195
|
|
|
196
|
+
assert [((0, 0), (1, 0)), ((0, 1), (1, 1))] == reader.get_sheet_by_name(
|
|
197
|
+
"Merged Cells"
|
|
198
|
+
).merged_cell_ranges
|
|
199
|
+
|
|
188
200
|
|
|
189
201
|
def test_xlsx_iter_rows():
|
|
190
|
-
names = ["Sheet1", "Sheet2", "Sheet3"]
|
|
202
|
+
names = ["Sheet1", "Sheet2", "Sheet3", "Merged Cells"]
|
|
191
203
|
data = [
|
|
192
204
|
["", "", "", "", "", "", "", "", "", ""],
|
|
193
205
|
[
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|