OdfFormatReader - правка по результатам тестирования (условное форматирование)

This commit is contained in:
ElenaSubbotina
2016-06-08 16:42:37 +03:00
parent e4cb386918
commit 1eb4acf708
8 changed files with 493 additions and 420 deletions

View File

@ -19,10 +19,10 @@ public:
std::wstring convert(std::wstring const & expr);
// $<24><><EFBFBD><EFBFBD>1.$A$1 -> <20><><EFBFBD><EFBFBD>1!$A$1
std::wstring convert_named_ref(std::wstring const & expr);
std::wstring convert_named_ref(std::wstring const & expr, bool withTableName = true);
//a-la convert without check formula
std::wstring convert_named_expr(std::wstring const & expr);
std::wstring convert_named_expr(std::wstring const & expr, bool withTableName = true);
//Sheet2.C3:Sheet2.C19 -> Sheet2!C3:C19
std::wstring convert_chart_distance(std::wstring const & expr);

View File

@ -10,18 +10,26 @@ namespace formulasconvert {
class odf2oox_converter::Impl
{
public:
static bool convert_with_TableName;
std::wstring convert(const std::wstring& expr);
std::wstring convert_chart_distance(const std::wstring& expr);
void replace_cells_range(std::wstring& expr);
void replace_cells_range(std::wstring& expr, bool withTableName);
bool check_formula(std::wstring& expr);
void replace_semicolons(std::wstring& expr);
void replace_vertical(std::wstring& expr);
void replace_space(std::wstring& expr);
void replace_named_ref(std::wstring & expr);
static std::wstring replace_named_ref_formater(boost::wsmatch const & what);
static std::wstring replace_named_ref_formater1(boost::wsmatch const & what);
static std::wstring replace_cell_range_formater(boost::wsmatch const & what);
void replace_named_ref(std::wstring & expr, bool w = true);
bool find_first_ref(std::wstring const & expr, std::wstring & table, std::wstring & ref);
bool find_first_last_ref(std::wstring const & expr, std::wstring & table, std::wstring & ref_first,std::wstring & ref_last);
};
bool odf2oox_converter::Impl::convert_with_TableName = true;
bool odf2oox_converter::Impl::find_first_last_ref(std::wstring const & expr, std::wstring & table,std::wstring & ref_first,std::wstring & ref_last)
{
std::vector< std::wstring > splitted;
@ -69,7 +77,8 @@ namespace formulasconvert {
return false;
}
std::wstring replace_cell_range_formater(boost::wsmatch const & what)
std::wstring odf2oox_converter::Impl::replace_cell_range_formater(boost::wsmatch const & what)
{
const size_t sz = what.size();
if (sz == 4 && !what[1].matched)
@ -93,7 +102,7 @@ namespace formulasconvert {
return L"";
}
std::wstring replace_named_ref_formater(boost::wsmatch const & what)
std::wstring odf2oox_converter::Impl::replace_named_ref_formater(boost::wsmatch const & what)
{
const size_t sz = what.size();
@ -111,12 +120,37 @@ namespace formulasconvert {
const std::wstring c1 = what[2].str();
const std::wstring c2 = what[3].str();
const std::wstring s = sheet1 + L"!" + c1 + (c2.empty() ? L"" : (L":" + c2) );
return s;
if (convert_with_TableName)
{
return (sheet1 + L"!") + c1 + (c2.empty() ? L"" : (L":" + c2) );
}
else
{
return c1 + (c2.empty() ? L"" : (L":" + c2) );
}
}
else if (sz == 5 && what[1].matched)
{
std::wstring sheet1 = what[1].str();
boost::algorithm::replace_all(sheet1, L"$", L"");
const std::wstring c1 = what[2].str();
const std::wstring c2 = what[3].str(); //sheet name 2
const std::wstring c3 = what[4].str();
if (convert_with_TableName)
{
return (sheet1 + L"!") + c1 + (c2.empty() ? L"" : (L":" + c3) );
}
else
{
return c1 + (c3.empty() ? L"" : (L":" + c3) );
}
}
return L"";
}
std::wstring replace_named_ref_formater1(boost::wsmatch const & what)
std::wstring odf2oox_converter::Impl::replace_named_ref_formater1(boost::wsmatch const & what)
{
boost::wregex complexRef(L"\\${0,1}([^\\.]+?){0,1}\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)(?::\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)){0,1}");
@ -132,386 +166,367 @@ namespace formulasconvert {
}
// заменяем формат адресации ячеек
// [.A1] -> A1
// [.A1:.B5] -> A1:B5
// [Sheet2.A1:B5] -> Sheet2!A1:B5
// [Sheet2.A1] -> Sheet2!A1
// [$'Sheet2 A'.$B2] -> 'Sheet2 A'!$B2
void odf2oox_converter::Impl::replace_cells_range(std::wstring& expr)
{
//boost::wregex simpleRef(L"\\[\\.([a-zA-Z]+\\d+)(?::\\.([a-zA-Z]+\\d+)){0,1}\\]");
boost::wregex complexRef(L"\\[(?:\\$)?([^\\.]+?){0,1}\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)(?::\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)){0,1}\\]");
/*
[ $ Sheet2 . A1 : . B5 ]
*/
const std::wstring res = boost::regex_replace(
expr,
complexRef,
&replace_named_ref_formater,
boost::match_default | boost::format_all);
expr = res;
}
void odf2oox_converter::Impl::replace_named_ref(std::wstring & expr)
{
boost::wregex complexRef(L"\\${0,1}([^\\.]+?){0,1}\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)(?::\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)){0,1}");
const std::wstring res = boost::regex_replace(
expr,
complexRef,
&replace_named_ref_formater,
boost::match_default | boost::format_all);
expr = res;
}
// распознаем и заменяем формат формулы
// of:=(Formula) -> (Formula)
bool odf2oox_converter::Impl::check_formula(std::wstring& expr)
{
boost::match_results<std::wstring::const_iterator> res;
if (boost::regex_search(expr, res, boost::wregex(L"(?:[\\w]+:)?=(.+)"), boost::match_default))
{
expr = res[1].str();
return true;
}
else
return false;
}
namespace
{
std::wstring replace_semicolons_formater(boost::wsmatch const & what)
{
if (what[1].matched)
return L",";
else if (what[2].matched)
return what[2].str();
else if (what[3].matched)
return what[3].str();
//else if (what[4].matched)
// return what[4].str();
else
return L"";
}
}
// TODO
// заменить точки с запятой во всех вхождениях кроме находящихся в кавычках --*и в фигурных скобках*--
// TODO: проверить как сохраняются кавычки в строке
void odf2oox_converter::Impl::replace_semicolons(std::wstring& expr)
{
const std::wstring res = boost::regex_replace(
expr,
//boost::wregex(L"(;)|(?:\".*?\")|(?:'.*?')"),
boost::wregex(L"(;)|(\".*?\")|('.*?')"),
&replace_semicolons_formater,
boost::match_default | boost::format_all);
expr = res;
}
namespace
{
std::wstring replace_vertical_formater(boost::wsmatch const & what)
{
if (what[1].matched)
{
std::wstring inner = what[1].str();
boost::algorithm::replace_all(inner, L"|", L";");
return L"{" + inner + L"}";
}
else if (what[2].matched)
return what[2].str();
else if (what[3].matched)
return what[3].str();
}
std::wstring replace_space_PROBEL(boost::wsmatch const & what)
{
if (what[1].matched)
{
std::wstring inner = what[1].str();
boost::algorithm::replace_all(inner, L" ", L"PROBEL");
return inner;
}
else if (what[2].matched)
return what[2].str();
else if (what[3].matched)
return what[3].str();
}
std::wstring replace_point(boost::wsmatch const & what)
{
if (what[1].matched)
{
std::wstring inner = what[1].str();
boost::algorithm::replace_all(inner, L".", L"ТОСHKA");
return inner;
}
else if (what[2].matched)
return what[2].str();
else if (what[3].matched)
return what[3].str();
}
std::wstring replace_space_formater(boost::wsmatch const & what)
{
if (what[1].matched)
{
std::wstring inner = what[1].str();
boost::algorithm::replace_all(inner, L" ", L",");
return inner;
}
else if (what[2].matched)
return what[2].str();
else if (what[3].matched)
return what[3].str();
}
}
std::wstring forbidden_formulas[] =
{
L"NULLFORMULA"
/*
L"BETADIST",
L"CEILING",
L"FLOOR",
L"RANK",
L"ROUND",
L"ROUNDDOWN",
L"ROUNDUP",
L"SUBTOTAL",
L"FORMULA",
L"ISREF"*/
};
bool is_forbidden(const std::wstring & formula)
{
BOOST_FOREACH(const std::wstring & s, forbidden_formulas)
{
if (boost::algorithm::contains(formula, s))
return true;
}
return false;
}
// заменить вертикальную черту во всех вхождениях в фигурных скобках, но не внутри строк
void odf2oox_converter::Impl::replace_vertical(std::wstring& expr)
{
const std::wstring res = boost::regex_replace(
expr,
boost::wregex(L"(?:(?:\\{)([^\\}]*?)(?:\\}))|(\".*?\")|('.*?')"),
&replace_vertical_formater,
boost::match_default | boost::format_all);
expr = res;
}
// заменить пробел во всех вхождениях на запятую
void odf2oox_converter::Impl::replace_space(std::wstring& expr)
{
const std::wstring res = boost::regex_replace(
expr,
boost::wregex(L"(?:(?:\\{)([^\\}]*?)(?:\\}))|(\".*?\")|('.*?')"),
&replace_space_formater,
boost::match_default | boost::format_all);
expr = res;
}
std::wstring odf2oox_converter::Impl::convert(const std::wstring& expr)
{
if (is_forbidden(expr))
return L"NULLFORMULA()";
boost::wregex complexRef(L"('(?!\\s\\'){0,1}.*?')");// поиск того что в апострофах и замена там точек на ТОСHKA
std::wstring workstr = boost::regex_replace(
expr,
complexRef,
&replace_point,
boost::match_default | boost::format_all);
boost::algorithm::replace_all(workstr, L" ", L"PROBEL");
boost::algorithm::replace_all(workstr, L"'", L"APOSTROF");
check_formula(workstr);
replace_cells_range(workstr);
replace_semicolons(workstr);
replace_vertical(workstr);
int res_find=0;
if ((res_find = workstr.find(L"CONCATINATE")) > 0)
// заменяем формат адресации ячеек
// [.A1] -> A1
// [.A1:.B5] -> A1:B5
// [Sheet2.A1:B5] -> Sheet2!A1:B5
// [Sheet2.A1] -> Sheet2!A1
// [$'Sheet2 A'.$B2] -> 'Sheet2 A'!$B2
void odf2oox_converter::Impl::replace_cells_range(std::wstring& expr, bool withTableName)
{
//могут быть частично заданы диапазоны
//todooo
convert_with_TableName = withTableName;
//boost::wregex simpleRef(L"\\[\\.([a-zA-Z]+\\d+)(?::\\.([a-zA-Z]+\\d+)){0,1}\\]");
boost::wregex complexRef(L"\\[(?:\\$)?([^\\.]+?){0,1}\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)(?::\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)){0,1}\\]");
/*
[ $ Sheet2 . A1 : . B5 ]
*/
const std::wstring res = boost::regex_replace(
expr,
complexRef,
&replace_named_ref_formater,
boost::match_default | boost::format_all);
expr = res;
}
boost::algorithm::replace_all(workstr, L"PROBEL" , L" ");
boost::algorithm::replace_all(workstr, L"APOSTROF" , L"'");
boost::algorithm::replace_all(workstr, L"TOCHKA" , L".");
return workstr;
}
//Sheet2.C3:Sheet2.C19 Sheet2.L29:Sheet2.L36
//в
//Sheet2!C3:C19,Sheet2!L27:L34
std::wstring odf2oox_converter::Impl::convert_chart_distance(const std::wstring& expr)
{
if (is_forbidden(expr))
return L"NULLFORMULA()";
std::wstring workstr = expr;
boost::wregex complexRef(L"('(?!\\s\\'){0,1}.*?')");// поиск того что в апострофах и замена там пробелов на PROBEL
workstr = boost::regex_replace(
expr,
complexRef,
&replace_space_PROBEL,
boost::match_default | boost::format_all);
//распарсить по диапазонам - одф-пробел, ик-эль-запятая
std::vector<std::wstring> distance_inp;
std::vector<std::wstring> distance_out;
boost::algorithm::split(distance_inp, workstr, boost::algorithm::is_any_of(L" "), boost::algorithm::token_compress_on);
BOOST_FOREACH(std::wstring &d,distance_inp)
void odf2oox_converter::Impl::replace_named_ref(std::wstring & expr, bool withTableName)
{
std::wstring sheet;
std::vector<std::wstring> range;
std::vector<std::wstring> cells;
boost::algorithm::split(range,d, boost::algorithm::is_any_of(L":"), boost::algorithm::token_compress_on);
BOOST_FOREACH(std::wstring &c,range)
{
const ::std::string::size_type colon = c.find('.');
cells.push_back(c.substr(colon+1));
if (sheet.size()<1)
sheet=c.substr(0, colon);
}
std::wstring cells_out;
BOOST_FOREACH(std::wstring &c,cells)
{
cells_out.append(c);
cells_out.append(L":");
}
int res1 = sheet.find(L"-");
int res2 = sheet.find(L"'");
convert_with_TableName = withTableName;
if (res1 >= 0 && !(res2 == 0))
//boost::wregex complexRef(L"\\${0,1}([^\\.]+?){0,1}\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)(?::\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)){0,1}");
boost::wregex complexRef(L"\\${0,1}([^\\.\\s]+?){0,1}\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)(?::\\${0,1}([^\\.\\s]+?){0,1}\\.(\\${0,1}[a-zA-Z]+\\${0,1}\\d+)){0,1}");
const std::wstring res = boost::regex_replace(
expr,
complexRef,
&replace_named_ref_formater,
boost::match_default | boost::format_all);
expr = res;
}
// распознаем и заменяем формат формулы
// of:=(Formula) -> (Formula)
bool odf2oox_converter::Impl::check_formula(std::wstring& expr)
{
boost::match_results<std::wstring::const_iterator> res;
if (boost::regex_search(expr, res, boost::wregex(L"(?:[\\w]+:)?=(.+)"), boost::match_default))
{
sheet = L"'" + sheet + L"'";
expr = res[1].str();
return true;
}
distance_out.push_back(sheet+L"!" + cells_out.substr(0, cells_out.size()-1));
else
return false;
}
std::wstring result;
BOOST_FOREACH(std::wstring &d, distance_out)
std::wstring replace_semicolons_formater(boost::wsmatch const & what)
{
result.append(d);
result.append(L",");
if (what[1].matched)
return L",";
else if (what[2].matched)
return what[2].str();
else if (what[3].matched)
return what[3].str();
//else if (what[4].matched)
// return what[4].str();
else
return L"";
}
boost::algorithm::replace_all(result, L"PROBEL", L" ");
return result.substr(0, result.size()-1);// минус последняя лишняя запятая
}
odf2oox_converter::odf2oox_converter(): impl_(new odf2oox_converter::Impl)
{
}
odf2oox_converter::~odf2oox_converter()
{
}
std::wstring odf2oox_converter::convert(const std::wstring& expr)
{
return impl_->convert(expr);
}
std::wstring odf2oox_converter::convert_chart_distance(const std::wstring& expr)
{
return impl_->convert_chart_distance(expr);
}
std::wstring odf2oox_converter::convert_named_ref(const std::wstring& expr)
{
boost::wregex complexRef(L"('(?!\\s\\'){0,1}.*?')");// поиск того что в апострофах и замена там точек на ТОСHKA
std::wstring workstr = boost::regex_replace(
expr,
complexRef,
&replace_point,
boost::match_default | boost::format_all);
boost::algorithm::replace_all(workstr, L" ", L"PROBEL");
boost::algorithm::replace_all(workstr, L"'", L"APOSTROF");
impl_->replace_named_ref(workstr);
boost::algorithm::replace_all(workstr, L"PROBEL" , L" ");
boost::algorithm::replace_all(workstr, L"APOSTROF" , L"'");
boost::algorithm::replace_all(workstr, L"TOCHKA" , L".");
return workstr;
}
std::wstring odf2oox_converter::convert_named_expr(const std::wstring& expr)
{
boost::wregex complexRef(L"('(?!\\s\\'){0,1}.*?')");// поиск того что в апострофах и замена там точек на ТОСHKA
std::wstring workstr = boost::regex_replace(
expr,
complexRef,
&replace_point,
boost::match_default | boost::format_all);
boost::algorithm::replace_all(workstr, L" ", L"PROBEL");
boost::algorithm::replace_all(workstr, L"'", L"APOSTROF");
impl_->replace_cells_range(workstr);
impl_->replace_semicolons(workstr);
impl_->replace_vertical(workstr);
int res_find=0;
if ((res_find = workstr.find(L"CONCATINATE")) > 0)
// TODO
// заменить точки с запятой во всех вхождениях кроме находящихся в кавычках --*и в фигурных скобках*--
// TODO: проверить как сохраняются кавычки в строке
void odf2oox_converter::Impl::replace_semicolons(std::wstring& expr)
{
//могут быть частично заданы диапазоны
//todooo
const std::wstring res = boost::regex_replace(
expr,
//boost::wregex(L"(;)|(?:\".*?\")|(?:'.*?')"),
boost::wregex(L"(;)|(\".*?\")|('.*?')"),
&replace_semicolons_formater,
boost::match_default | boost::format_all);
expr = res;
}
boost::algorithm::replace_all(workstr, L"PROBEL" , L" ");
boost::algorithm::replace_all(workstr, L"APOSTROF" , L"'");
boost::algorithm::replace_all(workstr, L"TOCHKA" , L".");
return workstr;
}
std::wstring odf2oox_converter::convert_ref(std::wstring const & expr)
{
std::wstring workstr = L"[" + expr + L"]";
impl_->replace_cells_range(workstr);
return workstr;
}
std::wstring odf2oox_converter::convert_spacechar(std::wstring expr)
{
while(true)
std::wstring replace_vertical_formater(boost::wsmatch const & what)
{
int pos = expr.find(L"%20");
if (pos <0)break;
expr.replace(pos,3,L" ");
if (what[1].matched)
{
std::wstring inner = what[1].str();
boost::algorithm::replace_all(inner, L"|", L";");
return L"{" + inner + L"}";
}
else if (what[2].matched)
return what[2].str();
else if (what[3].matched)
return what[3].str();
}
return expr;
}
bool odf2oox_converter::find_first_ref(std::wstring const & expr, std::wstring & table, std::wstring & ref)
{
return impl_->find_first_ref(expr, table, ref);
}
bool odf2oox_converter::find_first_last_ref(std::wstring const & expr, std::wstring & table, std::wstring & ref_first,std::wstring & ref_last)
{
return impl_->find_first_last_ref(expr, table, ref_first,ref_last);
}
std::wstring replace_point_space(boost::wsmatch const & what)
{
if (what[1].matched)
{
std::wstring inner = what[1].str();
boost::algorithm::replace_all(inner, L".", L"ТОСHKA");
boost::algorithm::replace_all(inner, L" ", L"PROBEL");
return inner;
}
else if (what[2].matched)
return what[2].str();
else if (what[3].matched)
return what[3].str();
}
std::wstring replace_space_formater(boost::wsmatch const & what)
{
if (what[1].matched)
{
std::wstring inner = what[1].str();
boost::algorithm::replace_all(inner, L" ", L",");
return inner;
}
else if (what[2].matched)
return what[2].str();
else if (what[3].matched)
return what[3].str();
}
std::wstring forbidden_formulas[] =
{
L"NULLFORMULA"
/*
L"BETADIST",
L"CEILING",
L"FLOOR",
L"RANK",
L"ROUND",
L"ROUNDDOWN",
L"ROUNDUP",
L"SUBTOTAL",
L"FORMULA",
L"ISREF"*/
};
bool is_forbidden(const std::wstring & formula)
{
BOOST_FOREACH(const std::wstring & s, forbidden_formulas)
{
if (boost::algorithm::contains(formula, s))
return true;
}
return false;
}
// заменить вертикальную черту во всех вхождениях в фигурных скобках, но не внутри строк
void odf2oox_converter::Impl::replace_vertical(std::wstring& expr)
{
const std::wstring res = boost::regex_replace(
expr,
boost::wregex(L"(?:(?:\\{)([^\\}]*?)(?:\\}))|(\".*?\")|('.*?')"),
&replace_vertical_formater,
boost::match_default | boost::format_all);
expr = res;
}
// заменить пробел во всех вхождениях на запятую
void odf2oox_converter::Impl::replace_space(std::wstring& expr)
{
const std::wstring res = boost::regex_replace(
expr,
boost::wregex(L"(?:(?:\\{)([^\\}]*?)(?:\\}))|(\".*?\")|('.*?')"),
&replace_space_formater,
boost::match_default | boost::format_all);
expr = res;
}
std::wstring odf2oox_converter::Impl::convert(const std::wstring& expr)
{
if (is_forbidden(expr))
return L"NULLFORMULA()";
boost::wregex complexRef(L"('(?!\\s\\'){0,1}.*?')");
std::wstring workstr = boost::regex_replace(
expr,
complexRef,
&replace_point_space,
boost::match_default | boost::format_all);
boost::algorithm::replace_all(workstr, L"'", L"APOSTROF");
check_formula(workstr);
replace_cells_range(workstr, true);
replace_semicolons(workstr);
replace_vertical(workstr);
int res_find=0;
if ((res_find = workstr.find(L"CONCATINATE")) > 0)
{
//могут быть частично заданы диапазоны
//todooo
}
boost::algorithm::replace_all(workstr, L"PROBEL" , L" ");
boost::algorithm::replace_all(workstr, L"APOSTROF" , L"'");
boost::algorithm::replace_all(workstr, L"TOCHKA" , L".");
return workstr;
}
//Sheet2.C3:Sheet2.C19 Sheet2.L29:Sheet2.L36
//в
//Sheet2!C3:C19,Sheet2!L27:L34
std::wstring odf2oox_converter::Impl::convert_chart_distance(const std::wstring& expr)
{
if (is_forbidden(expr))
return L"NULLFORMULA()";
std::wstring workstr = expr;
boost::wregex complexRef(L"('(?!\\s\\'){0,1}.*?')");// поиск того что в апострофах и замена там
workstr = boost::regex_replace(
expr,
complexRef,
&replace_point_space,
boost::match_default | boost::format_all);
//распарсить по диапазонам - одф-пробел, ик-эль-запятая
std::vector<std::wstring> distance_inp;
std::vector<std::wstring> distance_out;
boost::algorithm::split(distance_inp, workstr, boost::algorithm::is_any_of(L" "), boost::algorithm::token_compress_on);
BOOST_FOREACH(std::wstring &d,distance_inp)
{
std::wstring sheet;
std::vector<std::wstring> range;
std::vector<std::wstring> cells;
boost::algorithm::split(range,d, boost::algorithm::is_any_of(L":"), boost::algorithm::token_compress_on);
BOOST_FOREACH(std::wstring &c,range)
{
const ::std::string::size_type colon = c.find('.');
cells.push_back(c.substr(colon+1));
if (sheet.size()<1)
sheet=c.substr(0, colon);
}
std::wstring cells_out;
BOOST_FOREACH(std::wstring &c,cells)
{
cells_out.append(c);
cells_out.append(L":");
}
int res1 = sheet.find(L"-");
int res2 = sheet.find(L"'");
if (res1 >= 0 && !(res2 == 0))
{
sheet = L"'" + sheet + L"'";
}
distance_out.push_back(sheet+L"!" + cells_out.substr(0, cells_out.size()-1));
}
std::wstring result;
BOOST_FOREACH(std::wstring &d, distance_out)
{
result.append(d);
result.append(L",");
}
boost::algorithm::replace_all(result, L"PROBEL" , L" ");
boost::algorithm::replace_all(result, L"TOCHKA" , L".");
return result.substr(0, result.size()-1);// минус последняя лишняя запятая
}
odf2oox_converter::odf2oox_converter(): impl_(new odf2oox_converter::Impl)
{
}
odf2oox_converter::~odf2oox_converter()
{
}
std::wstring odf2oox_converter::convert(const std::wstring& expr)
{
return impl_->convert(expr);
}
std::wstring odf2oox_converter::convert_chart_distance(const std::wstring& expr)
{
return impl_->convert_chart_distance(expr);
}
std::wstring odf2oox_converter::convert_named_ref(const std::wstring& expr, bool withTableName)
{
boost::wregex complexRef(L"('(?!\\s\\'){0,1}.*?')");// поиск того что в апострофах и замена там
std::wstring workstr = boost::regex_replace(
expr,
complexRef,
&replace_point_space,
boost::match_default | boost::format_all);
boost::algorithm::replace_all(workstr, L"'", L"APOSTROF");
impl_->replace_named_ref(workstr, withTableName);
boost::algorithm::replace_all(workstr, L"PROBEL" , L" ");
boost::algorithm::replace_all(workstr, L"APOSTROF" , L"'");
boost::algorithm::replace_all(workstr, L"TOCHKA" , L".");
return workstr;
}
std::wstring odf2oox_converter::convert_named_expr(const std::wstring& expr, bool withTableName)
{
boost::wregex complexRef(L"('(?!\\s\\'){0,1}.*?')");// поиск того что в апострофах и замена там
std::wstring workstr = boost::regex_replace(
expr,
complexRef,
&replace_point_space,
boost::match_default | boost::format_all);
boost::algorithm::replace_all(workstr, L"'", L"APOSTROF");
impl_->replace_cells_range(workstr, withTableName);
impl_->replace_semicolons(workstr);
impl_->replace_vertical(workstr);
int res_find=0;
if ((res_find = workstr.find(L"CONCATINATE")) > 0)
{
//могут быть частично заданы диапазоны
//todooo
}
boost::algorithm::replace_all(workstr, L"PROBEL" , L" ");
boost::algorithm::replace_all(workstr, L"APOSTROF" , L"'");
boost::algorithm::replace_all(workstr, L"TOCHKA" , L".");
return workstr;
}
std::wstring odf2oox_converter::convert_ref(std::wstring const & expr)
{
std::wstring workstr = L"[" + expr + L"]";
impl_->replace_cells_range(workstr, true);
return workstr;
}
std::wstring odf2oox_converter::convert_spacechar(std::wstring expr)
{
while(true)
{
int pos = expr.find(L"%20");
if (pos <0)break;
expr.replace(pos,3,L" ");
}
return expr;
}
bool odf2oox_converter::find_first_ref(std::wstring const & expr, std::wstring & table, std::wstring & ref)
{
return impl_->find_first_ref(expr, table, ref);
}
bool odf2oox_converter::find_first_last_ref(std::wstring const & expr, std::wstring & table, std::wstring & ref_first,std::wstring & ref_last)
{
return impl_->find_first_last_ref(expr, table, ref_first, ref_last);
}
}
}

View File

@ -26,6 +26,7 @@ public:
static std::wstring replace_cells_range_formater2(boost::wsmatch const & what);
static std::wstring replace_arguments(boost::wsmatch const & what);
static std::wstring convert_scobci(boost::wsmatch const & what);
std::wstring replace_arguments1(std::wstring & workstr);
void replace_named_ref(std::wstring & expr);

View File

@ -30,9 +30,12 @@ namespace oox {
case 3: CP_XML_ATTR(L"type", L"min"); break;
case 4: CP_XML_ATTR(L"type", L"max"); break; //todooo ext - autoMax
case 5: CP_XML_ATTR(L"type", L"min"); break;
case 6: CP_XML_ATTR(L"type", L"formula"); break;
}
if (val)
if (val)
{
CP_XML_ATTR(L"val", *val);
}
}
}
}
@ -47,6 +50,7 @@ namespace oox {
_CP_OPT(std::wstring) operator_;
//expr
_CP_OPT(std::wstring) formula;
_CP_OPT(std::wstring) formula_type;
//color scale icon set data_bar
std::vector<_cfvo> cfvo;
//color scale data_bar(1 element)
@ -81,13 +85,16 @@ public:
for (int i = 0 ; i < conditionalFormattings_.size(); i++)
{
conditionalFormatting & c = conditionalFormattings_[i];
CP_XML_NODE(L"conditionalFormatting")
if (c.rules.size() < 1) continue;
CP_XML_NODE(L"conditionalFormatting")
{
CP_XML_ATTR(L"sqref", c.ref);
for (int j = 0 ; j < c.rules.size(); j++)
{
if (c.rules[j].type < 1 || c.rules[j].type > 4) continue;
if (c.rules[j].type < 1 || c.rules[j].type > 5) continue;
CP_XML_NODE(L"cfRule")
{
@ -105,7 +112,7 @@ public:
//CP_XML_ATTR(L"aboveAverage" , 0);
if (c.rules[j].type == 1)
{
CP_XML_ATTR(L"type", L"expression");
CP_XML_ATTR(L"type", *c.rules[j].formula_type);
if (c.rules[j].formula)
{
CP_XML_NODE(L"formula")
@ -195,26 +202,7 @@ void xlsx_conditionalFormatting_context::add(std::wstring ref)
formulasconvert::odf2oox_converter converter;
impl_->conditionalFormattings_.push_back(conditionalFormatting());
ref = converter.convert_named_ref(ref);
//'Fitness Plan'!N20:'Fitness Plan'!P22; K25 -> N20:P22
int pos_cells = ref.find(L":");
std::wstring ref2;
if (pos_cells >0)
{
ref2 = ref.substr(pos_cells + 1);
ref = ref.substr(0, pos_cells);
pos_cells = ref2.find(L"!");
if (pos_cells > 0)
ref2 = ref2.substr(pos_cells + 1);
}
pos_cells = ref.find(L"!");
if (pos_cells > 0)
ref = ref.substr(pos_cells + 1);
if (!ref2.empty()) ref += L":" + ref2;
impl_->conditionalFormattings_.back().ref = ref;
impl_->conditionalFormattings_.back().ref = converter.convert_named_ref(ref, false);
}
void xlsx_conditionalFormatting_context::add_rule(int type)
@ -225,13 +213,73 @@ void xlsx_conditionalFormatting_context::add_rule(int type)
}
void xlsx_conditionalFormatting_context::set_formula(std::wstring f)
{
int pos = f.find(L"formula-is(");
if ( pos >= 0 )
int pos = -1;
std::wstring val;
if ( 0 <= (pos = f.find(L"formula-is(")))
{
f = f.substr(11, f.size() - 12);
impl_->conditionalFormattings_.back().rules.back().formula_type = L"expression";
val = f.substr(11, f.size() - 12);
}
else if (0 <= (pos = f.find(L"is-between(")))
{
}
else if (0 <= (pos = f.find(L"is-time(")))
{
}
else
{
impl_->conditionalFormattings_.back().rules.back().formula_type = L"cellIs";
if (0 <= (pos = f.find(L"!empty")))
{
}
else if (0 <= (pos = f.find(L"empty")))
{
}
else if (0 <= (pos = f.find(L"bottom")))
{
}
else if (0 <= (pos = f.find(L"top")))
{
}
else if (0 <= (pos = f.find(L"!=")))
{
impl_->conditionalFormattings_.back().rules.back().operator_ = L"notEqual";
val = f.substr(2);
}
else if (0 <= (pos = f.find(L"<=")))
{
impl_->conditionalFormattings_.back().rules.back().operator_ = L"lessThanOrEqual";
val = f.substr(2);
}
else if (0 <= (pos = f.find(L">=")))
{
impl_->conditionalFormattings_.back().rules.back().operator_ = L"greaterThanOrEqual";
val = f.substr(2);
}
else if (0 <= (pos = f.find(L"=")))
{
impl_->conditionalFormattings_.back().rules.back().operator_ = L"equal";
val = f.substr(1);
}
else if (0 <= (pos = f.find(L"<")))
{
impl_->conditionalFormattings_.back().rules.back().operator_ = L"lessThan";
val = f.substr(1);
}
else if (0 <= (pos = f.find(L">")))
{
impl_->conditionalFormattings_.back().rules.back().operator_ = L"greaterThan";
val = f.substr(1);
}
else
{
val = f;
}
}
formulasconvert::odf2oox_converter converter;
impl_->conditionalFormattings_.back().rules.back().formula = converter.convert_named_expr(f);
impl_->conditionalFormattings_.back().rules.back().formula = converter.convert_named_expr(val);
}
void xlsx_conditionalFormatting_context::set_dataBar(_CP_OPT(int) min, _CP_OPT(int) max)
{
@ -246,7 +294,15 @@ void xlsx_conditionalFormatting_context::add_sfv(int type, std::wstring value)
{
_cfvo cfvo;
cfvo.type = type;
if (!value.empty()) cfvo.val = value;
if ( type == 6)
{
set_formula(value);
cfvo.val =impl_->conditionalFormattings_.back().rules.back().formula;
impl_->conditionalFormattings_.back().rules.back().formula.reset();
}
else if (!value.empty()) cfvo.val = value;
impl_->conditionalFormattings_.back().rules.back().cfvo.push_back(cfvo);
}

View File

@ -63,8 +63,8 @@ void xlsx_dxfs::serialize(std::wostream & _Wostream) const
{
CP_XML_NODE(L"dxf")
{
xlsx_serialize(CP_XML_STREAM(), impl_->dxf_array[i].fill);
xlsx_serialize(CP_XML_STREAM(), impl_->dxf_array[i].font);
xlsx_serialize(CP_XML_STREAM(), impl_->dxf_array[i].fill);
}
}
}

View File

@ -51,9 +51,10 @@ calcext_type calcext_type::parse(const std::wstring & Str)
return calcext_type( Maximum );
else if (tmp == L"minimum")
return calcext_type( Minimum );
else if (tmp == L"formula")
return calcext_type( Formula );
else
{
BOOST_THROW_EXCEPTION( errors::invalid_attribute() );
return calcext_type( Number );
}
}

View File

@ -17,7 +17,8 @@ public:
Maximum,
Minimum,
AutoMaximum,
AutoMinimum
AutoMinimum,
Formula
};
calcext_type() {}

View File

@ -72,43 +72,42 @@ iconset_type iconset_type::parse(const std::wstring & Str)
std::wstring tmp = Str;
boost::algorithm::to_lower(tmp);
if (tmp == L"3Arrows")
if (tmp == L"3arrows")
return iconset_type( Arrows3 );
else if (tmp == L"3ArrowsGray")
else if (tmp == L"3arrowsgray")
return iconset_type( Arrows3Gray );
else if (tmp == L"3Flags")
else if (tmp == L"3flags")
return iconset_type( Flags3 );
else if (tmp == L"3Signs")
else if (tmp == L"3signs")
return iconset_type( Signs3 );
else if (tmp == L"3Symbols")
else if (tmp == L"3symbols")
return iconset_type( Symbols3 );
else if (tmp == L"3Symbols2")
else if (tmp == L"3symbols2")
return iconset_type( Symbols3_2 );
else if (tmp == L"3TrafficLights1")
else if (tmp == L"3trafficlights1")
return iconset_type( Traffic3Lights1 );
else if (tmp == L"3TrafficLights2")
else if (tmp == L"3trafficlights2")
return iconset_type( Traffic3Lights2 );
else if (tmp == L"4Arrows")
else if (tmp == L"4arrows")
return iconset_type( Arrows4 );
else if (tmp == L"4ArrowsGray")
else if (tmp == L"4arrowsgray")
return iconset_type( Arrows4Gray );
else if (tmp == L"4Rating")
return iconset_type( Rating4 );
else if (tmp == L"4RedToBlack")
else if (tmp == L"4redtoblack")
return iconset_type( RedToBlack4 );
else if (tmp == L"4TrafficLights")
else if (tmp == L"4trafficlights")
return iconset_type( Traffic4Lights );
else if (tmp == L"5Arrows")
else if (tmp == L"5arrows")
return iconset_type( Arrows5 );
else if (tmp == L"5ArrowsGray")
else if (tmp == L"5arrowsgray")
return iconset_type( Arrows5Gray );
else if (tmp == L"5Quarters")
else if (tmp == L"5quarters")
return iconset_type( Quarters5 );
else if (tmp == L"5Rating")
else if (tmp == L"5rating")
return iconset_type( Rating5 );
else
{
BOOST_THROW_EXCEPTION( errors::invalid_attribute() );
return iconset_type( Arrows3 );
}
}