refactoring convert ods formula

This commit is contained in:
ElenaSubbotina
2024-12-07 11:49:52 +03:00
parent d69601c2d2
commit a08b614bce
2 changed files with 79 additions and 286 deletions

View File

@ -79,7 +79,7 @@ namespace formulasconvert {
static bool convert_with_absolute;
static bool convert_with_TableName;
static std::wstring table_name_;
static std::vector<std::map<std::wstring, std::wstring>> mapReplacements;
//-------------------------------------------------------------------------------------------------------------
static std::wstring replace_apersand_formater(boost::wsmatch const & what)
{
@ -146,75 +146,29 @@ namespace formulasconvert {
static void replace_tmp_back(std::wstring &expr)
{
XmlUtils::replace_all( expr, L"ТОСHKA", L".");
XmlUtils::replace_all( expr, L"VOSKL", L"!");
XmlUtils::replace_all( expr, L"SCOBCAIN", L"(");
XmlUtils::replace_all( expr, L"SCOBCAOUT", L")");
//XmlUtils::replace_all( expr, L"KVADRATIN", L"[");
//XmlUtils::replace_all( expr, L"KVADRATOUT", L"]");
XmlUtils::replace_all( expr, L"PROBEL", L" ");
//XmlUtils::replace_all( expr, L"APOSTROF", L"'");
//XmlUtils::replace_all( expr, L"KAVYCHKA", L"\"");
XmlUtils::replace_all(expr, L"APERSAND", L"&");
for (auto key : mapReplacements.back())
{
XmlUtils::replace_all(expr, key.first, key.second);
}
}
static void replace_tmp(std::wstring &expr)
{
// XmlUtils::replace_all( expr, L".", L"ТОСHKA");
// XmlUtils::replace_all( expr, L"!", L"VOSKL");
//std::random_device genSource;
//std::uniform_int_distribution<> generator(0, 23);
//for (int index = 0; index < 5; index++)
//{
// key += wchar_t(L'a' + generator(genSource));
//}
// XmlUtils::replace_all( expr, L"(", L"SCOBCAIN");
// XmlUtils::replace_all( expr, L")", L"SCOBCAOUT");
// //XmlUtils::replace_all( expr, L"[", L"KVADRATIN");
// //XmlUtils::replace_all( expr, L"]", L"KVADRATOUT");
//
// XmlUtils::replace_all( expr, L" ", L"PROBEL");
//// XmlUtils::replace_all( expr, L"'", L"APOSTROF");
//// XmlUtils::replace_all( expr, L"\"", L"KAVYCHKA");
std::wstring result;
size_t pos = 0, size = expr.length();
while(pos < size)
std::wstring key = L"aaaaaaaaaaaaaaaaaaaaaaaa";
for (unsigned i = 0; i < 23; ++i)
{
switch(expr[pos])
{
case '.':
{
result += L"ТОСHKA";
}break;
case '!':
{
result += L"VOSKL";
}break;
case '(':
{
result += L"SCOBCAIN";
}break;
case ')':
{
result += L"SCOBCAOUT";
}break;
case ' ':
{
result += L"PROBEL";
}break;
case '&':
{
result += L"APERSAND";
}break;
default:
{
result += expr[pos];
}break;
}
pos++;
unsigned j = rand() % (i + 1);
key[i] = key[j];
key[j] = wchar_t(L'a' + i);
}
expr = result;
mapReplacements.back().insert(std::make_pair(key, expr));
expr = key;
}
static std::wstring convert_scobci(boost::wsmatch const & what)
{
@ -278,12 +232,16 @@ namespace formulasconvert {
bool odf2oox_converter::Impl::convert_with_TableName = true;
std::wstring odf2oox_converter::Impl::table_name_ = L"";
bool odf2oox_converter::Impl::convert_with_absolute = false;
std::vector<std::map<std::wstring, std::wstring>> odf2oox_converter::Impl::mapReplacements;
std::unordered_map<std::wstring, int> &odf2oox_converter::Impl::mapExternalLink_ = oox::xlsx_conversion_context::mapExternalLink_;
bool odf2oox_converter::Impl::find_first_last_ref(std::wstring const & expr, std::wstring & table,std::wstring & ref_first,std::wstring & ref_last)
{
std::wstring workstr = expr;
mapReplacements.emplace_back();
workstr = boost::regex_replace(
workstr,
boost::wregex(L"('.*?')|(\".*?\")"),
@ -317,6 +275,7 @@ namespace formulasconvert {
}
replace_tmp_back( table );
mapReplacements.pop_back();
return res;
}
@ -637,7 +596,9 @@ namespace formulasconvert {
bool isFormula = check_formula(workstr);
//экранирование
workstr = boost::regex_replace(workstr,
mapReplacements.emplace_back();
workstr = boost::regex_replace(workstr,
boost::wregex(L"('.*?')|(\".*?\")"),
&convert_scobci, boost::match_default | boost::format_all);
@ -671,11 +632,14 @@ namespace formulasconvert {
//-----------------------------------------------------------
replace_tmp_back(workstr);
mapReplacements.pop_back();
return workstr;
}
void odf2oox_converter::Impl::split_distance_by(const std::wstring& expr, const std::wstring& by, std::vector<std::wstring>& out)
{
mapReplacements.emplace_back();
std::wstring workstr = boost::regex_replace(
expr,
boost::wregex(L"('.*?')|(\".*?\")"),
@ -687,6 +651,7 @@ namespace formulasconvert {
{
replace_tmp_back(out[i]);
}
mapReplacements.pop_back();
}
//Sheet2.C3:Sheet2.C19 Sheet2.L29:Sheet2.L36
@ -701,6 +666,8 @@ namespace formulasconvert {
std::wstring odf2oox_converter::Impl::convert_chart_distance(const std::wstring& expr)
{
mapReplacements.emplace_back();
std::wstring workstr = boost::regex_replace(
is_forbidden(expr),
boost::wregex(L"('.*?')|(\".*?\")"),
@ -758,6 +725,7 @@ namespace formulasconvert {
}
replace_tmp_back( result );
mapReplacements.pop_back();
return result.substr(0, result.size() - 1);// минус последняя лишняя запятая
}
std::wstring odf2oox_converter::Impl::convert_named_ref(const std::wstring& expr, bool withTableName, std::wstring separator, bool bAbsoluteAlways)
@ -766,6 +734,8 @@ namespace formulasconvert {
std::wstring workstr = expr;
mapReplacements.emplace_back();
workstr = boost::regex_replace(
workstr,
boost::wregex(L"('.*?')|(\".*?\")"),
@ -784,6 +754,7 @@ namespace formulasconvert {
{
replace_tmp_back( table_name_ );
}
mapReplacements.pop_back();
return workstr;
}
std::wstring odf2oox_converter::Impl::convert_named_expr(const std::wstring& expr, bool withTableName, bool bAbsoluteAlways)
@ -798,12 +769,12 @@ namespace formulasconvert {
}
else
{
mapReplacements.emplace_back();
workstr = boost::regex_replace(
workstr,
boost::wregex(L"('.*?')|(\".*?\")"),
&convert_scobci, boost::match_default | boost::format_all);
workstr = replace_cells_range(workstr, withTableName, bAbsoluteAlways);
replace_semicolons(workstr);
@ -822,6 +793,7 @@ namespace formulasconvert {
{
replace_tmp_back(table_name_);
}
mapReplacements.pop_back();
}
return workstr;
}

View File

@ -36,6 +36,7 @@
#include"../../OOXML/Base/Unit.h"
#include "boost/lexical_cast.hpp"
//#include <random>
namespace cpdoccore {
namespace formulasconvert {
@ -76,6 +77,8 @@ public:
static std::wstring replace_arguments(boost::wsmatch const & what);
static std::wstring convert_scobci(boost::wsmatch const & what);
static std::vector<std::map<std::wstring, std::wstring>> mapReplacements;
static std::wstring replace_tilda_formater(boost::wsmatch const & what)
{
if (what[1].matched)
@ -132,227 +135,37 @@ public:
return L"";
}
static void oox_replace_tmp_back(std::wstring &expr)
static void oox_replace_tmp_back(std::wstring& expr)
{
std::wstring result;
size_t pos = 0, size = expr.length();
while(pos < size)
for (auto key : mapReplacements.back())
{
if (pos + 5 >= size)
{
result += expr[pos++];
continue;
}
switch(expr[pos])
{
case 'M':
{
if ((pos + 5 <= size) && (expr.substr(pos, 5) == L"MINYS"))
{
result += L"-"; pos += 5;
}
else
{
result += expr[pos++];
}
}break;
case 'T':
{
if ((pos + 6 <= size) && (expr.substr(pos, 6) == L"TОСHKA"))
{
result += L"."; pos += 6;
}
else
{
result += expr[pos++];
}
}break;
case 'V':
{
if ((pos + 5 <= size) && (expr.substr(pos, 5) == L"VOSKL"))
{
result += L"!"; pos += 5;
}
else
{
result += expr[pos++];
}
}break;
case 'S':
{
if ((pos + 8 <= size) && (expr.substr(pos, 8) == L"SCOBCAIN"))
{
result += L"("; pos += 8;
}
else if ((pos + 9 <= size) && (expr.substr(pos, 9) == L"SCOBCAOUT"))
{
result += L")"; pos += 9;
}
else
{
result += expr[pos++];
}
}break;
case 'K':
{
if ((pos + 9 <= size) && (expr.substr(pos, 9) == L"KVADRATIN"))
{
result += L"["; pos += 9;
}
else if ((pos + 10 <= size) && (expr.substr(pos, 10) == L"KVADRATOUT"))
{
result += L"]"; pos += 10;
}
else if ((pos + 8 <= size) && (expr.substr(pos, 8) == L"KAVYCHKA"))
{
result += L"\""; pos += 8;
}
else
{
result += expr[pos++];
}
}break;
case 'P':
{
if ((pos + 6 <= size) && (expr.substr(pos, 6) == L"PROBEL"))
{
result += L" "; pos += 6;
}
else
{
result += expr[pos++];
}
}break;
case 'A':
{
if ((pos + 8 <= size) && (expr.substr(pos, 8) == L"APOSTROF"))
{
result += L"'"; pos += 8;
}
else if ((pos + 8 <= size) && (expr.substr(pos, 8) == L"APERSAND"))
{
result += L"&"; pos += 8;
}
else
{
result += expr[pos++];
}
}break;
case 'Z':
{
if ((pos + 9 <= size) && (expr.substr(pos, 9) == L"ZAPYATAYA"))
{
result += L","; pos += 9;
}
else
{
result += expr[pos++];
}
}break;
default:
{
result += expr[pos++];
}break;
}
XmlUtils::replace_all(expr, key.first, key.second);
}
expr = result;
//XmlUtils::replace_all( expr, L"MINYS", L"-");
//XmlUtils::replace_all( expr, L"TОСHKA", L".");
//XmlUtils::replace_all( expr, L"VOSKL", L"!");
//XmlUtils::replace_all( expr, L"SCOBCAIN", L"(");
//XmlUtils::replace_all( expr, L"SCOBCAOUT", L")");
XmlUtils::replace_all(expr, L"KVADRATIN", L"[");
XmlUtils::replace_all(expr, L"KVADRATOUT", L"]");
//XmlUtils::replace_all( expr, L"KVADRATIN", L"[");
//XmlUtils::replace_all( expr, L"KVADRATOUT", L"]");
//
//XmlUtils::replace_all( expr, L"PROBEL", L" ");
//XmlUtils::replace_all( expr, L"APOSTROF", L"'");
//XmlUtils::replace_all( expr, L"KAVYCHKA", L"\"");
return;
}
static void oox_replace_tmp(std::wstring &expr)
{
std::wstring result;
//std::random_device genSource;
//std::uniform_int_distribution<> generator(0, 23);
//for (int index = 0; index < 5; index++)
//{
// key += wchar_t(L'a' + generator(genSource));
//}
size_t pos = 0, size = expr.length();
while(pos < size)
std::wstring key = L"aaaaaaaaaaaaaaaaaaaaaaaa";
for (unsigned i = 0; i < 23; ++i)
{
switch(expr[pos])
{
case '-':
{
result += L"MINYS";
}break;
case '.':
{
result += L"TОСHKA";
}break;
case ',':
{
result += L"ZAPYATAYA";
}break;
case '!':
{
result += L"VOSKL";
}break;
case '(':
{
result += L"SCOBCAIN";
}break;
case ')':
{
result += L"SCOBCAOUT";
}break;
case '[':
{
result += L"KVADRATIN";
}break;
case ']':
{
result += L"KVADRATOUT";
}break;
case ' ':
{
result += L"PROBEL";
}break;
case '\'':
{
result += L"APOSTROF";
}break;
case '\"':
{
result += L"KAVYCHKA";
}break;
case '&':
{
result += L"APERSAND";
}break;
default:
{
result += expr[pos];
}break;
}
pos++;
unsigned j = rand() % (i + 1);
key[i] = key[j];
key[j] = wchar_t(L'a' + i);
}
expr = result;
//XmlUtils::replace_all( expr, L"-", L"MINYS");
//XmlUtils::replace_all( expr, L".", L"TОСHKA");
//XmlUtils::replace_all( expr, L"!", L"VOSKL");
//XmlUtils::replace_all( expr, L"(", L"SCOBCAIN");
//XmlUtils::replace_all( expr, L")", L"SCOBCAOUT");
//XmlUtils::replace_all( expr, L"[", L"KVADRATIN");
//XmlUtils::replace_all( expr, L"]", L"KVADRATOUT");
//
//XmlUtils::replace_all( expr, L" ", L"PROBEL");
//XmlUtils::replace_all( expr, L"'", L"APOSTROF");
//XmlUtils::replace_all( expr, L"\"", L"KAVYCHKA");
mapReplacements.back().insert(std::make_pair(key, expr));
expr = key;
}
static bool is_forbidden1(const std::wstring & formula)
@ -375,6 +188,7 @@ public:
bool oox2odf_converter::Impl::isFindBaseCell_ = false;
std::wstring oox2odf_converter::Impl::table_name_ = L"";
std::vector<std::map<std::wstring, std::wstring>> oox2odf_converter::Impl::mapReplacements;
void oox2odf_converter::Impl::replace_cells_range(std::wstring& expr, bool bSelect)
{
@ -612,7 +426,9 @@ void oox2odf_converter::Impl::replace_named_ref(std::wstring & expr)
isFindBaseCell_ = true;
std::wstring workstr = expr, out;
mapReplacements.emplace_back();
replace_vertical(workstr);
replace_semicolons(workstr);
@ -644,6 +460,7 @@ void oox2odf_converter::Impl::replace_named_ref(std::wstring & expr)
{
oox_replace_tmp_back(table_name_);
}
mapReplacements.pop_back();
}
@ -699,7 +516,7 @@ std::wstring oox2odf_converter::Impl::convert_scobci(boost::wsmatch const & what
if (what[1].matched)
{
std::wstring inner = what[1].str();
oox_replace_tmp(inner);
oox_replace_tmp(inner);
return inner;
}
else if (what[2].matched)
@ -761,13 +578,14 @@ std::wstring oox2odf_converter::Impl::convert(const std::wstring& expr)
return workstr;
}
// (Formula) -> of:=(Formula)
std::wstring oox2odf_converter::Impl::convert_formula(const std::wstring & expr)
{
{
std::wstring workstr = expr;
mapReplacements.emplace_back();
std::wstring res1 = boost::regex_replace(
workstr,
workstr,
boost::wregex(L"('.*?')|(\".*?\")"),
&oox2odf_converter::Impl::convert_scobci, boost::match_default | boost::format_all);
@ -782,7 +600,7 @@ std::wstring oox2odf_converter::Impl::convert_formula(const std::wstring & expr)
if (res1 == res)
{
XmlUtils::replace_all( res1, L"KAVYCHKA", L"\""); //IMCONJUGATE_emb.xlsx
//XmlUtils::replace_all( res1, L"KAVYCHKA", L"\""); //IMCONJUGATE_emb.xlsx
res = boost::regex_replace(
res1,
@ -796,13 +614,13 @@ std::wstring oox2odf_converter::Impl::convert_formula(const std::wstring & expr)
replace_vertical(res);
replace_semicolons(res);
XmlUtils::replace_all( res, L"PROBEL", L" ");
if (table_name_.empty() == false)
{
oox_replace_tmp_back(table_name_);
}
mapReplacements.pop_back();
return std::wstring(L"of:=") + res;
}
@ -810,6 +628,8 @@ std::wstring oox2odf_converter::Impl::convert_conditional_formula(const std::wst
{
std::wstring workstr = expr;
mapReplacements.emplace_back();
std::wstring res1 = boost::regex_replace(
workstr,
boost::wregex(L"('.*?')|(\".*?\")"),
@ -829,13 +649,14 @@ std::wstring oox2odf_converter::Impl::convert_conditional_formula(const std::wst
}
XmlUtils::replace_all(res, L"&", L"&amp;");
//XmlUtils::replace_all(res, L"&", L"&amp;");
oox_replace_tmp_back( res);
replace_vertical(res);
replace_semicolons(res);
XmlUtils::replace_all( res, L"PROBEL", L" ");
mapReplacements.pop_back();
//XmlUtils::replace_all( res, L"PROBEL", L" ");
return res;