Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[xlsb] fix more array fmls #1042

Merged
merged 3 commits into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions R/class-workbook.R
Original file line number Diff line number Diff line change
Expand Up @@ -3309,19 +3309,22 @@ wbWorkbook <- R6::R6Class(
}, FUN.VALUE = ""), collapse = "")
if (WR != "") {
WR <- rbindlist(xml_attr(WR, "Relationships", "Relationship"))
WR$tmpDirPartName <- paste0(tmpDir, "/xl/", folder, "/", WR$Target)
WR$fileExists <- file.exists(WR$tmpDirPartName)

# exclude hyperlinks
WR$type <- basename(WR$Type)
WR <- WR[WR$type != "hyperlink", ]

if (!all(WR$fileExists)) {
missing_in_tmp <- WR$Target[!WR$fileExists]
warning(
"[", folder, "] file expected to be in output is missing: ",
paste(missing_in_tmp, collapse = " ")
)

if (NROW(WR)) { # in xlsb files it can be that WR has no rows
WR$tmpDirPartName <- paste0(tmpDir, "/xl/", folder, "/", WR$Target)
WR$fileExists <- file.exists(WR$tmpDirPartName)

# exclude hyperlinks
WR$type <- basename(WR$Type)
WR <- WR[WR$type != "hyperlink", ]

if (!all(WR$fileExists)) {
missing_in_tmp <- WR$Target[!WR$fileExists]
warning(
"[", folder, "] file expected to be in output is missing: ",
paste(missing_in_tmp, collapse = " ")
)
}
}
}
}
Expand Down
63 changes: 51 additions & 12 deletions src/xlsb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ int table_bin(std::string filePath, std::string outPath, bool debug) {
if (bin) {
bin.seekg(0, std::ios_base::beg);
bool end_of_table = false;
bool has_revision_record = false;

while(!end_of_table) {
Rcpp::checkUserInterrupt();
Expand Down Expand Up @@ -893,7 +894,7 @@ int table_bin(std::string filePath, std::string outPath, bool debug) {
std::string fml;
flags = readbin(flags, bin, swapit);
int sharedFormula = false;
fml = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula);
fml = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula, has_revision_record);

// need to write this formula somehwere
if (debug )Rcpp::Rcout << fml << std::endl;
Expand Down Expand Up @@ -921,6 +922,18 @@ int table_bin(std::string filePath, std::string outPath, bool debug) {
break;
}

case BrtRRChgCell:
case BrtRRDefName:
{
has_revision_record = true;
// -- have not seen this yet. if it appears, treat it as if a revision record was found --
// rgce.rgce or rgceOld.rgce in BrtRRDefName
if (debug) Rcpp::Rcout << "BrtRRChgCell or BrtRRDefName" << std::endl;
Rcpp::warning("Assuming revision record.");
bin.seekg(size, bin.cur);
break;
}

default:
{
if (debug) {
Expand Down Expand Up @@ -1395,6 +1408,7 @@ int workbook_bin(std::string filePath, std::string outPath, bool debug) {
bin.seekg(0, std::ios_base::beg);
bool end_of_workbook = false;
bool first_extern_sheet = true;
bool has_revision_record = false;

std::vector<std::string> defNams, xtis, reference_type;
defNams.push_back("<definedNames>");
Expand Down Expand Up @@ -1654,7 +1668,7 @@ int workbook_bin(std::string filePath, std::string outPath, bool debug) {
std::string fml = "", comment = "";

int sharedFormula = false;
fml = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula);
fml = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula, has_revision_record);

comment = XLNullableWideString(bin, swapit);

Expand Down Expand Up @@ -1920,6 +1934,18 @@ int workbook_bin(std::string filePath, std::string outPath, bool debug) {
break;
}

case BrtRRChgCell:
case BrtRRDefName:
{
has_revision_record = true;
// -- have not seen this yet. if it appears, treat it as if a revision record was found --
// rgce.rgce or rgceOld.rgce in BrtRRDefName
if (debug) Rcpp::Rcout << "BrtRRChgCell or BrtRRDefName" << std::endl;
Rcpp::warning("Assuming revision record.");
bin.seekg(size, bin.cur);
break;
}

default:
{
if (debug) {
Expand Down Expand Up @@ -1961,6 +1987,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo
bool first_row = true;
bool in_sheet_data = false;
bool end_of_worksheet = false;
bool has_revision_record = false;
std::string fml_type;

uint32_t row = 0;
Expand Down Expand Up @@ -2810,7 +2837,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo
grbitFlags = readbin(grbitFlags, bin, swapit);

// GrbitFmlaFields *fields = (GrbitFmlaFields *)&grbitFlags;
std::string fml = CellParsedFormula(bin, swapit, debug, 0, row, is_shared_formula);
std::string fml = CellParsedFormula(bin, swapit, debug, 0, row, is_shared_formula, has_revision_record);



Expand Down Expand Up @@ -2858,7 +2885,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo
// int32_t len = size - 4 * 32 - 2 * 8;
// std::string fml(len, '\0');

std::string fml = CellParsedFormula(bin, swapit, debug, 0, row, is_shared_formula);
std::string fml = CellParsedFormula(bin, swapit, debug, 0, row, is_shared_formula, has_revision_record);

xml_col column;
column.v = fErr;
Expand Down Expand Up @@ -2906,7 +2933,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo
// fields->fAlwaysCalc,
// fields->unused);

std::string fml = CellParsedFormula(bin, swapit, debug, 0, row, is_shared_formula);
std::string fml = CellParsedFormula(bin, swapit, debug, 0, row, is_shared_formula, has_revision_record);

std::stringstream stream;
stream << std::setprecision(16) << xnum;
Expand Down Expand Up @@ -2957,7 +2984,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo
grbitFlags = readbin(grbitFlags, bin, swapit);


std::string fml = CellParsedFormula(bin, swapit, debug, 0, row, is_shared_formula);
std::string fml = CellParsedFormula(bin, swapit, debug, 0, row, is_shared_formula, has_revision_record);

// if (is_shared_formula) {
// Rcpp::Rcout << fml << std::endl;
Expand Down Expand Up @@ -3011,7 +3038,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo

flags = readbin(flags, bin, 0);

std::string fml = CellParsedFormula(bin, swapit, debug, col, row, is_shared_formula);
std::string fml = CellParsedFormula(bin, swapit, debug, col, row, is_shared_formula, has_revision_record);
if (debug) Rcpp::Rcout << "BrtArrFmla: " << fml << std::endl;

// add to the last colvec element
Expand Down Expand Up @@ -3056,7 +3083,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo

if (debug) Rcpp::Rcout << "ref: " << ref << std::endl;

std::string fml = CellParsedFormula(bin, swapit, debug, col, row, is_shared_formula);
std::string fml = CellParsedFormula(bin, swapit, debug, col, row, is_shared_formula, has_revision_record);
if (debug) Rcpp::Rcout << "BrtShrFmla: " << fml << std::endl;

fml_type = "shared";
Expand Down Expand Up @@ -3414,7 +3441,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo
std::string strProgID = XLNullableWideString(bin, swapit);

int sharedFormula = false;
if (fLinked) std::string link = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula);
if (fLinked) std::string link = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula, has_revision_record);

std::string stRelID = XLNullableWideString(bin, swapit);
out << "<oleObject progId=\"" << strProgID << "\" shapeId=\"" << shapeId << "\" r:id=\"" << stRelID << "\" />" << std::endl;
Expand Down Expand Up @@ -3507,13 +3534,13 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo
int sharedFormula = false;
std::string rgce1, rgce2, rgce3;
if (cbFmla1 != 0x00000000) {
rgce1 = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula);
rgce1 = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula, has_revision_record);
}
if (cbFmla2 != 0x00000000) {
rgce2 = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula);
rgce2 = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula, has_revision_record);
}
if (cbFmla3 != 0x00000000) {
rgce3 = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula);
rgce3 = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula, has_revision_record);
}

BrtBeginCFRuleFields *fields = (BrtBeginCFRuleFields *)&flags;
Expand Down Expand Up @@ -3644,6 +3671,18 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo
break;
}

case BrtRRChgCell:
case BrtRRDefName:
{
has_revision_record = true;
// -- have not seen this yet. if it appears, treat it as if a revision record was found --
// rgce.rgce or rgceOld.rgce in BrtRRDefName
if (debug) Rcpp::Rcout << "BrtRRChgCell or BrtRRDefName" << std::endl;
Rcpp::warning("Assuming revision record.");
bin.seekg(size, bin.cur);
break;
}

default:
{
// if (debug) {
Expand Down
13 changes: 13 additions & 0 deletions src/xlsb_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,19 @@ typedef struct {
uint16_t unused : 13;
} BrtWbPropFields;


typedef struct {
uint8_t columns : 2;
uint8_t rowType : 5;
bool squareBracketSpace : 1;
bool commaSpace : 1;
bool unused : 1;
uint8_t type : 2;
bool invalid : 1;
bool nonresident : 1;
uint8_t reserved2 : 2;
} PtgListFields;

enum RgbExtra
{
PtgExtraArray = 0,
Expand Down
Loading
Loading