1111 lines
28 KiB
C++
Executable File
1111 lines
28 KiB
C++
Executable File
#include <applicat.h>
|
|
#include <expr.h>
|
|
#include <msksheet.h>
|
|
#include <progind.h>
|
|
#include <relation.h>
|
|
#include <sheet.h>
|
|
#include <tabutil.h>
|
|
#include <urldefid.h>
|
|
#include <reputils.h>
|
|
|
|
#include "ve4.h"
|
|
#include "ve4100.h"
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TTable_expression
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TTable_expression : public TExpression
|
|
{
|
|
static TArray _expr;
|
|
static const TRelation* _rel;
|
|
static TLog_report* _win;
|
|
static bool _errors;
|
|
|
|
protected:
|
|
virtual bool print_error(const char* msg) const;
|
|
virtual int parse_user_func(const char* name, int nparms) const;
|
|
virtual void evaluate_user_func(int index, int nparms,
|
|
TEval_stack& stack, TTypeexp curtype) const;
|
|
virtual bool user_func_dirty() const;
|
|
|
|
bool error_box(const char* fmt, ...) const;
|
|
const TRelation& get_relation() const { CHECK(_rel, "NULL relation"); return *_rel; }
|
|
|
|
// Cerca il record dato il file->campo. Usata da get_field e put_field.
|
|
TRectype* field2rec(TString& var) const;
|
|
// Converte un nome di funzione in indice
|
|
int name2index(const char* name) const;
|
|
|
|
public:
|
|
static void load_table(bool force = false);
|
|
static void set_relation(const TRelation* rel) { _rel = rel; load_table(); }
|
|
static void set_window(TLog_report* win) { _win = win; }
|
|
static void reset_errors() { _errors = false; }
|
|
static bool errors_found() { return _errors; }
|
|
|
|
int str2file(const TString& s) const;
|
|
const char* get_field(const char* f) const;
|
|
void set_field(const char* field, const char* val) const;
|
|
|
|
TTable_expression() { }
|
|
virtual ~TTable_expression() { }
|
|
};
|
|
|
|
TArray TTable_expression::_expr;
|
|
const TRelation* TTable_expression::_rel = NULL;
|
|
TLog_report* TTable_expression::_win = NULL;
|
|
bool TTable_expression::_errors = false;
|
|
|
|
void TTable_expression::load_table(bool force)
|
|
{
|
|
if (_expr.items() == 0 || force)
|
|
{
|
|
TString n(15), e(127);
|
|
TTable expr("%FRM");
|
|
for (expr.first(); !expr.eof(); expr.next())
|
|
{
|
|
n = expr.get("CODTAB");
|
|
e = expr.get("S1");
|
|
e << expr.get("S2");
|
|
const TTypeexp t = expr.get_bool("B0") ? _strexpr : _numexpr;
|
|
|
|
TTable_expression* te = new TTable_expression;
|
|
THash_object* o = new THash_object(n, te);
|
|
const int index = _expr.add(o);
|
|
if (!te->set(e, t))
|
|
{
|
|
te->error_box(FR("La funzione %s contiene un simbolo errato: %s"),
|
|
(const char*)n, te->last_token());
|
|
te->set("", t);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TTable_expression::user_func_dirty() const
|
|
{
|
|
return _errors || TExpression::user_func_dirty();
|
|
}
|
|
|
|
bool TTable_expression::print_error(const char* msg) const
|
|
{
|
|
if (_win)
|
|
_win->log(2, msg);
|
|
else
|
|
::error_box(msg);
|
|
return _errors = true;
|
|
}
|
|
|
|
bool TTable_expression::error_box(const char* fmt, ...) const
|
|
{
|
|
char msg[256];
|
|
va_list argptr;
|
|
va_start(argptr,fmt);
|
|
vsprintf(msg, fmt, argptr);
|
|
va_end(argptr);
|
|
return print_error(msg);
|
|
}
|
|
|
|
int TTable_expression::str2file(const TString& str) const
|
|
{
|
|
int ln = -1;
|
|
if (isdigit(str[0]))
|
|
{
|
|
ln = atoi(str);
|
|
}
|
|
else
|
|
{
|
|
const char* const s = "AUDCR";
|
|
const int logicnum[] = { LF_ANAMAG, LF_UMART, LF_DESLIN, LF_CONDV, LF_RCONDV, 0 };
|
|
const char* p = strchr(s, toupper(str[0]));
|
|
ln = p != NULL ? logicnum[p-s] : -1;
|
|
}
|
|
|
|
return ln;
|
|
}
|
|
|
|
TRectype* TTable_expression::field2rec(TString& var) const
|
|
{
|
|
int logicnum = 0;
|
|
var.upper();
|
|
const int arrow = var.find("->");
|
|
if (arrow > 0)
|
|
{
|
|
logicnum = str2file(var);
|
|
var = var.mid(arrow+2);
|
|
}
|
|
|
|
TRectype* rec = NULL;
|
|
if (logicnum >= 0 && get_relation().exist(logicnum))
|
|
rec = &get_relation().curr(logicnum);
|
|
else
|
|
error_box(FR("Il campo '%s' non appartiene alla relazione."), (const char*)var);
|
|
return rec;
|
|
}
|
|
|
|
const char* TTable_expression::get_field(const char* f) const
|
|
{
|
|
TString var(f);
|
|
const TRectype* rec = field2rec(var);
|
|
const char* val = "";
|
|
if (rec != NULL)
|
|
{
|
|
if (rec->exist(var))
|
|
val = rec->get(var);
|
|
else
|
|
error_box(FR("Il campo '%s' non appartiene al file %d."), (const char*)var, rec->num());
|
|
}
|
|
return val;
|
|
}
|
|
|
|
void TTable_expression::set_field(const char* f, const char* v) const
|
|
{
|
|
TString var(f);
|
|
TRectype* rec = field2rec(var);
|
|
if (rec != NULL)
|
|
rec->put(var, v);
|
|
}
|
|
|
|
int TTable_expression::name2index(const char* name) const
|
|
{
|
|
if (_expr.items() == 0)
|
|
load_table();
|
|
|
|
TString code(name); code.upper();
|
|
int index;
|
|
|
|
for (index = _expr.items()-1; index >= 0; index--)
|
|
{
|
|
const THash_object& h = (const THash_object&)_expr[index];
|
|
if (h.key() == code)
|
|
break;
|
|
}
|
|
|
|
if (index < 0)
|
|
{
|
|
TTable expr("%FRM");
|
|
expr.put("CODTAB", code);
|
|
if (expr.read() == NOERR)
|
|
{
|
|
TString e(127);
|
|
e = expr.get("S1"); e << expr.get("S2");
|
|
const TTypeexp t = expr.get_bool("B0") ? _numexpr : _strexpr;
|
|
TTable_expression* te = new TTable_expression;
|
|
if (te->set(e, t))
|
|
{
|
|
THash_object* o = new THash_object(code, te);
|
|
index = _expr.add(o);
|
|
}
|
|
else
|
|
{
|
|
delete te;
|
|
index = -2;
|
|
}
|
|
}
|
|
}
|
|
return index;
|
|
}
|
|
|
|
int TTable_expression::parse_user_func(const char* name, int nparms) const
|
|
{
|
|
const int index = name2index(name);
|
|
switch(index)
|
|
{
|
|
case -1:
|
|
error_box(FR("Funzione non riconosciuta: %s."), name);
|
|
break;
|
|
case -2:
|
|
error_box(FR("La funzione %s contiene un simbolo errato: %s."),
|
|
name, last_token());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return index;
|
|
}
|
|
|
|
void TTable_expression::evaluate_user_func(int index, int nparms,
|
|
TEval_stack& stack, TTypeexp curtype) const
|
|
{
|
|
THash_object* ho = (THash_object*)_expr.objptr(index);
|
|
TTable_expression& expr = (TTable_expression&)ho->obj();
|
|
|
|
// Assegna i valori a tutte le variabili dell'espressione
|
|
for (int v = expr.numvar()-1; v >= 0; v--)
|
|
{
|
|
const char* var = expr.varname(v);
|
|
if (var[0] == '#') // Parametro della funzione
|
|
{
|
|
const int n = atoi(var+1);
|
|
if (n > 0 && n <= nparms)
|
|
{
|
|
const TObject& o = stack.peek(nparms-n);
|
|
if (o.class_id() == CLASS_STRING)
|
|
expr.setvar(var, (const TString&)o);
|
|
else
|
|
expr.setvar(var, (const real&)o);
|
|
}
|
|
else
|
|
error_box("Parametro non valido: %s", (const char*)var);
|
|
}
|
|
else
|
|
{
|
|
const char* val = get_field(var);
|
|
if (curtype == _numexpr)
|
|
expr.setvar(var, real(val));
|
|
else
|
|
expr.setvar(var, val);
|
|
}
|
|
}
|
|
|
|
// Toglie i parametri dallo stack
|
|
for (int p = nparms; p > 0; p--)
|
|
stack.pop();
|
|
|
|
// Mette il risultato sullo stack
|
|
if (curtype == _numexpr)
|
|
stack.push((const real&)expr);
|
|
else
|
|
stack.push((const TString&)expr);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Maschera ricalcolo di magazzino
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TRicalcolo_mask : public TMask
|
|
{
|
|
TArray _rel, _des;
|
|
int _cur_file;
|
|
TToken_string _key_expr;
|
|
|
|
TRelation* _relation;
|
|
TCursor* _cursor;
|
|
|
|
protected:
|
|
bool test_formula(TMask_field& f) const;
|
|
|
|
static bool file_handler (TMask_field& f, KEY k);
|
|
static bool key_handler (TMask_field& f, KEY k);
|
|
static bool filter_handler (TMask_field& f, KEY k);
|
|
static bool field_handler (TMask_field& f, KEY k);
|
|
static bool fromto_handler (TMask_field& f, KEY k);
|
|
static bool formula_handler(TMask_field& f, KEY k);
|
|
|
|
bool gestione_um(char tipo) const;
|
|
TRelation_description& get_des() const;
|
|
TRelation& get_rel() const;
|
|
const TRectype& get_rec() const;
|
|
const RecDes& get_rec_des() const;
|
|
TToken_string& get_key_expr(int k);
|
|
|
|
TRelation& create_relation();
|
|
TCursor& create_cursor();
|
|
|
|
public:
|
|
bool elabora();
|
|
|
|
TRicalcolo_mask();
|
|
virtual ~TRicalcolo_mask() { }
|
|
};
|
|
|
|
TRicalcolo_mask::TRicalcolo_mask()
|
|
: TMask("ve4100"), _cur_file(0), _relation(NULL), _cursor(NULL)
|
|
{
|
|
const int lf[] = { LF_ANAMAG, LF_UMART, LF_DESLIN, LF_CONDV, LF_RCONDV, LF_CLIFO, LF_CFBAN, LF_CFVEN, 0 };
|
|
for (int i = 0; lf[i]; i++)
|
|
{
|
|
TRelation* rel = new TRelation(lf[i]);
|
|
_rel.add(rel);
|
|
_des.add(new TRelation_description(*rel));
|
|
}
|
|
|
|
set_handler(F_FILE, file_handler);
|
|
set_handler(F_KEY, key_handler);
|
|
set_handler(F_FILTER, filter_handler);
|
|
|
|
TSheet_field& fields = sfield(F_FIELDS);
|
|
TMask& fsm = fields.sheet_mask();
|
|
fsm.set_handler(F_FIELD, field_handler);
|
|
fsm.set_handler(F_FROM, fromto_handler);
|
|
fsm.set_handler(F_TO, fromto_handler);
|
|
|
|
TSheet_field& outputs = sfield(F_OUTPUTS);
|
|
TMask& osm = outputs.sheet_mask();
|
|
osm.set_handler(F_FIELD, field_handler);
|
|
osm.set_handler(F_FORMULA, formula_handler);
|
|
outputs.row(-1); // Aggiunge comunque una riga vuota;
|
|
osm.force_update();
|
|
}
|
|
|
|
TRelation_description& TRicalcolo_mask::get_des() const
|
|
{
|
|
return (TRelation_description&)_des[_cur_file];
|
|
}
|
|
|
|
TRelation& TRicalcolo_mask::get_rel() const
|
|
{
|
|
return (TRelation&)_rel[_cur_file];
|
|
}
|
|
|
|
const TRectype& TRicalcolo_mask::get_rec() const
|
|
{
|
|
return get_rel().lfile().curr();
|
|
}
|
|
|
|
const RecDes& TRicalcolo_mask::get_rec_des() const
|
|
{
|
|
return get_rec().rec_des();
|
|
}
|
|
|
|
TToken_string& TRicalcolo_mask::get_key_expr(int key)
|
|
{
|
|
_key_expr.cut(0);
|
|
if (key > 0)
|
|
{
|
|
const RecDes& rd = get_rec_des();
|
|
const KeyDes& kd = rd.Ky[key-1];
|
|
for (int i = 0; i < kd.NkFields; i++)
|
|
{
|
|
const int nf = kd.FieldSeq[i] % MaxFields;
|
|
const RecFieldDes& rf = rd.Fd[nf];
|
|
_key_expr.add(rf.Name);
|
|
}
|
|
}
|
|
return _key_expr;
|
|
}
|
|
|
|
bool TRicalcolo_mask::gestione_um(char tipo) const
|
|
{
|
|
const char* const lco = "LCO";
|
|
int i;
|
|
|
|
for (i = 0; i < 3 && toupper(tipo) != lco[i]; i++);
|
|
CHECK(i < 3, "Gestione unita' di misura errata");
|
|
TConfig ve(CONFIG_DITTA, "ve");
|
|
return ve.get_bool("GESUM", NULL, i+1);
|
|
}
|
|
|
|
TRelation& TRicalcolo_mask::create_relation()
|
|
{
|
|
const int logicnum = get_rec().num(); // Numero logico del file principale
|
|
if (_relation)
|
|
delete _relation;
|
|
_relation = new TRelation(logicnum);
|
|
|
|
const TString& unita_misura = get(F_UNITA_MISURA);
|
|
const TString& lingua = get(F_LINGUA);
|
|
|
|
const TString& tipo_lco = get(F_TIPO_LCO); // Listini, contratti, offerte
|
|
const TString& cat_ven = get(F_CAT_VEN);
|
|
const TString& tipo_cf = get(F_TIPO_CF);
|
|
const TString& codice_cf = get(F_CODICE_CF);
|
|
const TString& codice_lco = get(F_CODICE_LCO);
|
|
|
|
TString condv_expr;
|
|
if (cat_ven.not_empty() && codice_cf.not_empty() && codice_lco.not_empty())
|
|
{
|
|
condv_expr << "TIPO=\"" << tipo_lco << '"';
|
|
condv_expr << "|CATVEN=\"" << cat_ven << '"';
|
|
condv_expr << "|TIPOCF=\"" << tipo_cf << '"';
|
|
condv_expr << "|CODCF=\"" << codice_cf << '"';
|
|
condv_expr << "|COD=\"" << codice_lco << '"';
|
|
}
|
|
|
|
TString expr(48);
|
|
|
|
switch (logicnum)
|
|
{
|
|
case LF_ANAMAG:
|
|
{
|
|
expr = "CODART=CODART";
|
|
if (unita_misura.not_empty())
|
|
{
|
|
expr << "|UM=\"" << unita_misura << '"';
|
|
_relation->add(LF_UMART, expr, 2);
|
|
}
|
|
else
|
|
_relation->add(LF_UMART, expr, 1);
|
|
|
|
if (lingua.not_empty())
|
|
{
|
|
expr = "CODART=CODART";
|
|
expr << "|CODLIN=\"" << lingua << '"';
|
|
_relation->add(LF_DESLIN, expr, 2);
|
|
}
|
|
|
|
if (condv_expr.not_empty())
|
|
{
|
|
_relation->add(LF_CONDV, condv_expr, 1);
|
|
|
|
if (unita_misura.not_empty())
|
|
{
|
|
expr = condv_expr;
|
|
expr << "|TIPORIGA=\"A\"";
|
|
expr << "|CODRIGA=CODART";
|
|
expr << "|UM=\"" << unita_misura << '"';
|
|
_relation->add(LF_RCONDV, expr, 1);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case LF_UMART:
|
|
{
|
|
_relation->add(LF_ANAMAG, "CODART=CODART", 1);
|
|
|
|
if (lingua.not_empty())
|
|
{
|
|
expr = "CODART=CODART";
|
|
expr << "|CODLIN=\"" << lingua << '"';
|
|
_relation->add(LF_DESLIN, expr, 2);
|
|
}
|
|
|
|
if (condv_expr.not_empty())
|
|
{
|
|
_relation->add(LF_CONDV, condv_expr, 1);
|
|
expr = condv_expr;
|
|
expr << "|TIPORIGA=\"A\"";
|
|
expr << "|CODRIGA=CODART";
|
|
expr << "|UM=UM";
|
|
_relation->add(LF_RCONDV, expr, 1);
|
|
}
|
|
}
|
|
break;
|
|
case LF_DESLIN:
|
|
{
|
|
_relation->add(LF_ANAMAG, "CODART=CODART", 1);
|
|
|
|
expr = "CODART=CODART";
|
|
if (unita_misura.not_empty())
|
|
{
|
|
expr << "|UM=\"" << unita_misura << '"';
|
|
_relation->add(LF_UMART, expr, 2);
|
|
}
|
|
else
|
|
_relation->add(LF_UMART, expr, 1);
|
|
|
|
if (condv_expr.not_empty())
|
|
{
|
|
_relation->add(LF_CONDV, condv_expr, 1);
|
|
|
|
if (unita_misura.not_empty())
|
|
{
|
|
expr = condv_expr;
|
|
expr << "|TIPORIGA=\"A\"";
|
|
expr << "|CODRIGA=CODART";
|
|
expr << "|UM=\"" << unita_misura << '"';
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case LF_RCONDV:
|
|
{
|
|
_relation->add(LF_ANAMAG, "CODART=CODRIGA", 1);
|
|
|
|
if (gestione_um(tipo_lco[0]))
|
|
_relation->add(LF_UMART, "CODART=CODRIGA|UM=UM", 2);
|
|
|
|
if (lingua.not_empty())
|
|
{
|
|
expr = "CODART=CODRIGA";
|
|
expr << "|CODLIN=\"" << lingua << '"';
|
|
_relation->add(LF_DESLIN, expr, 2);
|
|
}
|
|
|
|
_relation->add(LF_RCONDV, "TIPO=TIPO|CATVEN=CATVEN|TIPOCF=TIPOCF|CODCF=CODCF|COD=COD", 1);
|
|
}
|
|
break;
|
|
case LF_CLIFO:
|
|
_relation->add(LF_CFVEN, "TIPOCF==TIPOCF|CODCF==CODCF");
|
|
break;
|
|
case LF_CFBAN:
|
|
{
|
|
_relation->add(LF_CLIFO, "TIPOCF==TIPOCF|CODCF==CODCF");
|
|
_relation->add(LF_CFVEN, "TIPOCF==TIPOCF|CODCF==CODCF");
|
|
}
|
|
break;
|
|
case LF_CFVEN:
|
|
_relation->add(LF_CLIFO, "TIPOCF==TIPOCF|CODCF==CODCF");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return *_relation;
|
|
}
|
|
|
|
TCursor& TRicalcolo_mask::create_cursor()
|
|
{
|
|
TString filter = get(F_FILTER); filter.strip("\n");
|
|
|
|
int key = get_int(F_KEY);
|
|
|
|
TRectype start(get_rec()), stop(get_rec());
|
|
start.zero(); stop.zero();
|
|
|
|
TToken_string& key_des = get_key_expr(key);
|
|
|
|
TSheet_field& fs = sfield(F_FIELDS);
|
|
TString16 field;
|
|
TString val;
|
|
|
|
// I primi campi corrispondono alla chiave selezionata?
|
|
bool key_seq_from = key > 0;
|
|
bool key_seq_to = key > 0;
|
|
|
|
for (int r = 0; r < fs.items(); r++)
|
|
{
|
|
TToken_string& row = fs.row(r);
|
|
field = row.get(0);
|
|
if (field.not_empty())
|
|
{
|
|
val = row.get(); // Limite inferiore
|
|
if (!val.blank())
|
|
{
|
|
if (key_seq_from && key_des.get_pos(field) == r)
|
|
start.put(field, val);
|
|
else
|
|
{
|
|
key_seq_from = false;
|
|
if (filter.not_empty()) filter << "&&";
|
|
filter << '(' << field << ">=\"" << val << "\")";
|
|
}
|
|
}
|
|
else
|
|
key_seq_from = false;
|
|
|
|
val = row.get(); // Limite superiore
|
|
if (!val.blank())
|
|
{
|
|
if (key_seq_to && key_des.get_pos(field) == r)
|
|
stop.put(field, val);
|
|
else
|
|
{
|
|
key_seq_to = false;
|
|
if (filter.not_empty()) filter << "&&";
|
|
filter << '(' << field << "<=\"" << val << "\")";
|
|
}
|
|
}
|
|
else
|
|
key_seq_to = false;
|
|
}
|
|
else
|
|
key_seq_from = key_seq_to = false;
|
|
}
|
|
|
|
if (key <= 0)
|
|
key = 1;
|
|
|
|
if (_cursor)
|
|
delete _cursor;
|
|
_cursor = new TCursor(&create_relation(), "", key, &start, &stop);
|
|
_cursor->setfilter(filter, filter.find("->") > 0); // Update relation when needed
|
|
return *_cursor;
|
|
}
|
|
|
|
bool TRicalcolo_mask::file_handler(TMask_field& f, KEY k)
|
|
{
|
|
TRicalcolo_mask& m = (TRicalcolo_mask&)f.mask();
|
|
if (k == K_SPACE && m.is_running())
|
|
{
|
|
const int n = atoi(f.get());
|
|
if (n != m._cur_file)
|
|
{
|
|
m._cur_file = n;
|
|
const RecDes& rd = m.get_rec_des();
|
|
const int keys = rd.NKeys;
|
|
|
|
TToken_string codes(16);
|
|
TToken_string values(80);
|
|
TString16 tmp;
|
|
codes.add(0);
|
|
values.add(TR("Nessuna"));
|
|
for (int k = 1; k <= keys; k++)
|
|
{
|
|
codes.add(k);
|
|
tmp.format(FR("Chiave %d"), k);
|
|
values.add(tmp);
|
|
}
|
|
|
|
TList_field& lk = m.lfield(F_KEY);
|
|
lk.replace_items(codes, values);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TRicalcolo_mask::key_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TRicalcolo_mask& m = (TRicalcolo_mask&)f.mask();
|
|
TSheet_field& sheet = m.sfield(F_FIELDS);
|
|
if (m.is_running() || sheet.items() == 0)
|
|
{
|
|
const int cur_key = atoi(f.get());
|
|
TToken_string& key_expr = m.get_key_expr(cur_key);
|
|
const bool empty = key_expr.empty_items();
|
|
int first_enabled = 0;
|
|
|
|
TString_array& sa = sheet.rows_array();
|
|
sa.destroy();
|
|
if (empty)
|
|
{
|
|
for (int i = 4; i >= 0; i--)
|
|
sa.add("");
|
|
}
|
|
else
|
|
{
|
|
TRelation_description& des = m.get_des();
|
|
for (TString field = key_expr.get(0); !field.blank(); field = key_expr.get())
|
|
{
|
|
const int r = sa.add(field);
|
|
sa.row(r).add(des.get_field_description(field), F_DESCR-F_FIELD);
|
|
}
|
|
if (des.file_num() == LF_CONDV || des.file_num() == LF_RCONDV)
|
|
{
|
|
first_enabled = 4;
|
|
TToken_string& row = sa.row(0);
|
|
const TString& lco = m.get(F_TIPO_LCO);
|
|
row.add(lco, 1);
|
|
row.add(lco, 2);
|
|
}
|
|
}
|
|
|
|
for (int r = sa.items()-1; r >= 0; r--)
|
|
sheet.enable_cell(0, -1, r >= first_enabled);
|
|
|
|
sheet.force_update();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TRicalcolo_mask::test_formula(TMask_field& f) const
|
|
{
|
|
TString filter(f.get()); filter.strip("\n");
|
|
TTable_expression expr;
|
|
bool ok = expr.set(filter, _strexpr);
|
|
if (ok)
|
|
{
|
|
TString var;
|
|
for (int v = expr.numvar()-1; v >= 0; v--)
|
|
{
|
|
int logicnum = 0;
|
|
var = expr.varname(v); var.upper();
|
|
const int arrow = var.find("->");
|
|
if (arrow >= 0)
|
|
{
|
|
logicnum = expr.str2file(var);
|
|
var = var.mid(arrow+2);
|
|
}
|
|
if (logicnum >= 0)
|
|
{
|
|
if (logicnum == 0)
|
|
ok = get_rec().exist(var);
|
|
else
|
|
{
|
|
TLocalisamfile lf(logicnum);
|
|
ok = lf.curr().exist(var);
|
|
}
|
|
}
|
|
else
|
|
ok = false;
|
|
if (!ok)
|
|
{
|
|
f.error_box("Il campo '%s' non esiste!", (const char*)expr.varname(v));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
f.error_box("Simbolo non riconosciuto: '%s'", expr.last_token());
|
|
return ok;
|
|
}
|
|
|
|
bool TRicalcolo_mask::filter_handler(TMask_field& f, KEY k)
|
|
{
|
|
bool ok = true;
|
|
if (f.to_check(k))
|
|
{
|
|
TRicalcolo_mask& m = (TRicalcolo_mask&)f.mask();
|
|
ok = m.test_formula(f);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TRicalcolo_mask::field_handler(TMask_field& f, KEY k)
|
|
{
|
|
bool ok = true;
|
|
switch (k)
|
|
{
|
|
case K_TAB:
|
|
case K_ENTER:
|
|
if (!f.empty() && f.to_check(k))
|
|
{
|
|
const TSheet_field& s = *f.mask().get_sheet();
|
|
TRicalcolo_mask& rm = (TRicalcolo_mask&)s.mask();
|
|
const TRectype& rec = rm.get_rec();
|
|
const TString16 field = f.get();
|
|
if (!rec.exist(field))
|
|
ok = f.error_box("Il campo '%s' non esiste.", (const char*)field);
|
|
if (ok && s.dlg() == F_OUTPUTS)
|
|
{
|
|
TToken_string& ke = rm.get_key_expr(1);
|
|
if (ke.get_pos(field) >= 0)
|
|
ok = f.error_box("Non e' possibile modificare un campo chiave.");
|
|
}
|
|
}
|
|
break;
|
|
case K_F9:
|
|
{
|
|
TMask& m = f.mask();
|
|
TRicalcolo_mask& rm = (TRicalcolo_mask&)m.get_sheet()->mask();
|
|
TRelation_description& rd = rm.get_des();
|
|
if (rd.choose_field(f.get()))
|
|
{
|
|
f.set(rd.field_name());
|
|
m.set(F_DESCR, rd.field_desc());
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
HIDDEN void swap_tokens(TToken_string& str, int p1, int p2)
|
|
{
|
|
const TString16 s1 = str.get(p1);
|
|
const TString16 s2 = str.get(p2);
|
|
str.add(s1, p2);
|
|
str.add(s2, p1);
|
|
}
|
|
|
|
bool TRicalcolo_mask::fromto_handler(TMask_field& f, KEY k)
|
|
{
|
|
bool ok = true;
|
|
if (f.to_check(k))
|
|
{
|
|
const TMask& m = f.mask();
|
|
const TString& field = m.get(F_FIELD);
|
|
if (field.not_empty())
|
|
{
|
|
TRicalcolo_mask& rm = (TRicalcolo_mask&)m.get_sheet()->mask();
|
|
const TRectype& rec = rm.get_rec();
|
|
const int max = rec.length(field);
|
|
if (f.get().len() > max)
|
|
{
|
|
TString msg(32); msg = "Inserire ";
|
|
if (max > 1) msg << max; else msg << "un";
|
|
msg << " caratter" << (max > 1 ? 'i' : 'e') << " al massimo.";
|
|
ok = f.error_box(msg);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (k == K_F9)
|
|
{
|
|
const TMask& m = f.mask();
|
|
TSheet_field& s = *m.get_sheet();
|
|
TRicalcolo_mask& rm = (TRicalcolo_mask&)s.mask();
|
|
TRelation& rel = rm.get_rel();
|
|
TRectype& rec = rel.curr();
|
|
TRelation_description& des = rm.get_des();
|
|
|
|
const TString title = des.file_desc();
|
|
|
|
TToken_string fields(256), head(256);
|
|
TString tmp;
|
|
for (int i = 0; i < rec.items(); i++)
|
|
{
|
|
tmp = rec.fieldname(i);
|
|
fields.add(tmp);
|
|
|
|
int lun = rec.length(tmp);
|
|
bool right = false;
|
|
switch(rec.type(tmp))
|
|
{
|
|
case _alfafld:
|
|
case _memofld:
|
|
if (lun > 50) lun = 50;
|
|
break;
|
|
case _charfld:
|
|
case _boolfld:
|
|
break;
|
|
case _datefld:
|
|
lun = 10;
|
|
break;
|
|
default:
|
|
right = true;
|
|
break;
|
|
}
|
|
tmp.lower(); tmp[0] = toupper(tmp[0]);
|
|
if (lun > tmp.len())
|
|
{
|
|
tmp << '@' << lun;
|
|
if (right) tmp << 'R';
|
|
}
|
|
else
|
|
{
|
|
if (right)
|
|
tmp << "@R";
|
|
}
|
|
head.add(tmp);
|
|
}
|
|
|
|
const int key = rm.get_int(F_KEY);
|
|
if (key > 0)
|
|
{
|
|
TToken_string& key_des = rm.get_key_expr(key);
|
|
int pos = 0;
|
|
for (TString c = key_des.get(0); c.not_empty(); c = key_des.get(), pos++)
|
|
{
|
|
const int p = fields.get_pos(c);
|
|
if (p != pos)
|
|
{
|
|
swap_tokens(fields, p, pos);
|
|
swap_tokens(head, p, pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEdit_field& e = (TEdit_field&)f;
|
|
|
|
TToken_string siblings;
|
|
siblings.add(e.dlg());
|
|
tmp = fields.get(0);
|
|
tmp = des.get_field_description(tmp);
|
|
if (tmp.len() > 30)
|
|
{
|
|
tmp.cut(27);
|
|
tmp << "...";
|
|
}
|
|
siblings.add(tmp);
|
|
|
|
TCursor cur(&rel, "", key > 0 ? key : 1);
|
|
TBrowse_sheet sheet(&cur, fields, title, head, 0, e, siblings);
|
|
if (sheet.run() == K_ENTER)
|
|
{
|
|
const TString16 field = s.row(s.selected()).get(0);
|
|
if (field.not_empty())
|
|
{
|
|
const TRectype& rec = cur.curr();
|
|
if (rec.exist(field))
|
|
{
|
|
cur = sheet.selected();
|
|
f.set(rec.get(field));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TRicalcolo_mask::formula_handler(TMask_field& f, KEY k)
|
|
{
|
|
bool ok = true;
|
|
if (f.to_check(k))
|
|
{
|
|
TRicalcolo_mask& m = (TRicalcolo_mask&)f.mask().get_sheet()->mask();
|
|
ok = m.test_formula(f);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Ciclo principale di elaborazione
|
|
///////////////////////////////////////////////////////////
|
|
|
|
HIDDEN bool rewrite_cursor(TCursor& cur)
|
|
{
|
|
bool ok = cur.lock(_lock) == NOERR;
|
|
if (ok)
|
|
{
|
|
ok = cur.relation()->rewrite() == NOERR;
|
|
cur.lock(_unlock);
|
|
}
|
|
if (!ok)
|
|
error_box("Impossibile aggiornare il record %ld.", cur.pos());
|
|
return ok;
|
|
}
|
|
|
|
bool TRicalcolo_mask::elabora()
|
|
{
|
|
TString16 var; // Nome di campo
|
|
TString val(80); // Valore di campo
|
|
TString line(128); // Linea di testo
|
|
|
|
TIndwin iw(48, TR("Inizializzazione..."), true, false, 48);
|
|
|
|
TCursor& cur = create_cursor(); // Crea e filtra il cursore principale
|
|
|
|
TSheet_field& osf = sfield(F_OUTPUTS);
|
|
TArray expr;
|
|
for (int r = 0; r < osf.items(); r++)
|
|
{
|
|
TToken_string& riga = osf.row(r);
|
|
var = riga.get(0);
|
|
if (var.not_empty())
|
|
{
|
|
TTypeexp tipo = _strexpr;
|
|
switch(cur.curr().type(var))
|
|
{
|
|
case _alfafld:
|
|
case _datefld:
|
|
case _memofld:
|
|
tipo = _strexpr;
|
|
break;
|
|
default:
|
|
tipo = _numexpr;
|
|
break;
|
|
}
|
|
line = riga.get(2);
|
|
TTable_expression* e = new TTable_expression;
|
|
e->set(line, tipo);
|
|
expr.add(e);
|
|
}
|
|
}
|
|
TToken_string& key_expr = get_key_expr(cur.key());
|
|
|
|
TLog_report vw(main_app().title());
|
|
|
|
TTable_expression::set_relation(cur.relation());
|
|
TTable_expression::set_window(&vw);
|
|
TTable_expression::reset_errors();
|
|
|
|
|
|
bool ok = true;
|
|
|
|
const TRecnotype items = cur.items();
|
|
cur.freeze();
|
|
|
|
for (cur = 0; cur.pos() < items; ++cur)
|
|
{
|
|
line.format("#%7ld - ", cur.pos()+1);
|
|
const TRectype& curr = cur.curr();
|
|
for (const char* f = key_expr.get(0); f; f = key_expr.get())
|
|
line << curr.get(f) << ' ';
|
|
vw.log(0, line);
|
|
|
|
for (int r = 0; r < osf.items(); r++)
|
|
{
|
|
var = osf.row(r).get(0);
|
|
if (var.not_empty())
|
|
{
|
|
TTable_expression& e = (TTable_expression&)expr[r];
|
|
for (int v = e.numvar()-1; v >= 0; v--)
|
|
{
|
|
var = e.varname(v);
|
|
val = e.get_field(var);
|
|
if (e.type() == _numexpr)
|
|
e.setvar(var, real(val));
|
|
else
|
|
e.setvar(var, val);
|
|
}
|
|
var = osf.row(r).get(0);
|
|
val = e;
|
|
|
|
if (e.errors_found())
|
|
ok = false;
|
|
else
|
|
{
|
|
cur.curr().put(var, val);
|
|
line.format("- %-10s = %s", (const char*)var, (const char*)val);
|
|
vw.log(0, line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TTable_expression::set_relation(NULL);
|
|
TTable_expression::set_window(NULL);
|
|
|
|
vw.preview();
|
|
|
|
if (get_bool(F_SAVE))
|
|
{
|
|
TString msg(80);
|
|
if (!ok)
|
|
msg = "Sono stati riscontrati degli errori di calcolo:\n";
|
|
msg << "Si desidera aggiornare effettivamente l'archivio?";
|
|
ok = yesno_box(msg);
|
|
if (ok)
|
|
{
|
|
TRecordset& rs = *vw.recordset();
|
|
TProgress_monitor piw(rs.items(), TR("Aggiornamento archivio"));
|
|
|
|
bool do_rewrite = false;
|
|
long pos = 0;
|
|
cur = 0L;
|
|
for (bool ok = rs.move_first(); ok; ok = rs.move_next())
|
|
{
|
|
if (!piw.add_status())
|
|
break;
|
|
line = rs.get(1).as_string();
|
|
if (line[0] == '#' && sscanf(line, "#%ld", &pos) == 1)
|
|
{
|
|
if (do_rewrite)
|
|
{
|
|
rewrite_cursor(cur);
|
|
do_rewrite = false;
|
|
}
|
|
cur = pos-1; // pos a video = 1 -> pos cursore = pos-1 = 0)
|
|
}
|
|
else
|
|
{
|
|
if (line[0] == '-' && sscanf(line, "- %s =", var.get_buffer()) == 1)
|
|
{
|
|
const char* equal = strchr(line, '=');
|
|
if (equal)
|
|
{
|
|
val = equal+2;
|
|
cur.curr().put(var, val);
|
|
do_rewrite = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (do_rewrite)
|
|
rewrite_cursor(cur);
|
|
}
|
|
}
|
|
cur.freeze(false);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Ricalcolo di magazzino
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TRicalcola_application : public TSkeleton_application
|
|
{
|
|
protected:
|
|
virtual void main_loop();
|
|
|
|
public:
|
|
// @cmember Disabilita la verifica del modulo in chiave
|
|
virtual bool check_autorization() const { return false; }
|
|
};
|
|
|
|
void TRicalcola_application::main_loop()
|
|
{
|
|
TRicalcolo_mask m;
|
|
m.open();
|
|
while (m.run() == K_ENTER)
|
|
m.elabora();
|
|
m.close();
|
|
}
|
|
|
|
int ve4100(int argc, char* argv[])
|
|
{
|
|
TRicalcola_application r;
|
|
r.run(argc, argv, TR("Ricalcolo valori"));
|
|
return 0;
|
|
}
|