diff --git a/autotest/ogr/data/xlsx/row_without_r_attribute.xlsx b/autotest/ogr/data/xlsx/row_without_r_attribute.xlsx new file mode 100644 index 000000000000..53fbf6b644cf Binary files /dev/null and b/autotest/ogr/data/xlsx/row_without_r_attribute.xlsx differ diff --git a/autotest/ogr/ogr_xlsx.py b/autotest/ogr/ogr_xlsx.py index f0c7a3a877c9..a4b8cc287935 100755 --- a/autotest/ogr/ogr_xlsx.py +++ b/autotest/ogr/ogr_xlsx.py @@ -649,3 +649,16 @@ def test_ogr_xlsx_read_xml_prefix(): f = lyr.GetNextFeature() assert f["Col1"] == "foo" assert f["Col2"] == "bar" + + +############################################################################### +# Test reading a XLSX file with without "r" attribute + + +def test_ogr_xlsx_read_row_without_r_attribute(): + + ds = ogr.Open("data/xlsx/row_without_r_attribute.xlsx") + lyr = ds.GetLayer(0) + f = lyr.GetNextFeature() + assert f["ID"] == 1 + assert f["NAME"] == "TEST123" diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp index 5f4fdf4544eb..f7d32b508e4a 100644 --- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp +++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp @@ -816,14 +816,22 @@ void OGRXLSXDataSource::startElementTable(const char *pszNameIn, apoCurLineValues.clear(); apoCurLineTypes.clear(); - int nNewCurLine = atoi(GetAttributeValue(ppszAttr, "r", "0")); - if (nNewCurLine <= 0) + int nNewCurLine; + if (const char *pszR = GetAttributeValue(ppszAttr, "r", nullptr)) { - CPLError(CE_Failure, CPLE_AppDefined, "Invalid row: %d", - nNewCurLine); - return; + nNewCurLine = atoi(pszR); + if (nNewCurLine <= 0) + { + CPLError(CE_Failure, CPLE_AppDefined, "Invalid row: %d", + nNewCurLine); + return; + } + nNewCurLine--; + } + else + { + nNewCurLine = nCurLine; } - nNewCurLine--; const int nFields = std::max( static_cast(apoFirstLineValues.size()), poCurLayer != nullptr ? poCurLayer->GetLayerDefn()->GetFieldCount()