#include "calib01.h" #include "calib02.h" #include "ca3883.h" #include "pconana.h" ///////////////////////////////////////////////////////////////////////////////// //Classe di report speciale con numero colonne adattabile in base ad un parametro ///////////////////////////////////////////////////////////////////////////////// void TCRPA_report::merge_array(TString_array& c, TString_array& t, TString_array& codici, TString_array& testate) const { while (c.items() > 0) { TObject* cod = c.remove(0,true); TObject* tes = t.remove(0,true); codici.TArray::add(cod); testate.TArray::add(tes); } } void TCRPA_report::analize_pconana_structure (const TString& prefix, const int depth, TString_array& codici, TString_array& testate) const { //cerca quale e' la lunghezza della stringa conto da considerare in base alla depth scelta TConfig& cfg = ca_config(); const TMultilevel_code_info& pconana_info = ca_multilevel_code_info(LF_PCONANA); const long total_length = pconana_info.total_len(depth); //scandisce il piano dei conti analitico alla ricerca dei conti di lunghezza pari a.. //..quella appena ricavata TISAM_recordset recset("USE PCONANA\nSELECT LEN(CODCONTO)=#LUN\nFROM CODCONTO=#PREFIX\nTO CODCONTO=#PREFIX"); recset.set_var("#LUN", TVariant(total_length)); recset.set_var("#PREFIX", TVariant(prefix)); const int prefix_length = prefix.len(); TString_array codici_c, testate_c, codici_r, testate_r; //riempie gli array con i codici conto di lunghezza opportuna e relative testate TString80 codice; for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { const TString& codconto = recset.get(PCONANA_CODCONTO).as_string(); const TAnal_bill zio(codconto); const int indbil = zio.indicatore_bilancio(); //solo Costi e Ricavi! if (indbil == 3 || indbil == 4) { codice.cut(0) << "#RECORD." << codconto.mid(prefix_length); const TString& testata = zio.testata(); if (indbil == 3) { codici_c.add(codice); testate_c.add(testata); } else { codici_r.add(codice); testate_r.add(testata); } } } if (codici_r.items() == 1) //se il campo da stampare e' uno solo->e' il totale del livello { codici_r.destroy(); testate_r.destroy(); } codici_r.add("#RICAVI"); testate_r.add(TR("RICAVI")); //..analogo per i Costi if (codici_c.items() == 1) { codici_c.destroy(); testate_c.destroy(); } codici_c.add("#COSTI"); testate_c.add(TR("COSTI")); //condensa gli array di Costo e Ricavo in un unico array che servira' di base per la stampa merge_array(codici_r, testate_r, codici, testate); merge_array(codici_c, testate_c, codici, testate); } //metodo per il riempimento e lo spostamento dei campi della sola sezione F4 (totali di commessa) void TCRPA_report::offset_and_fill_sectionf4(TReport_section& rep_sect, const int model_id) { //campo modello TReport_field& rep_field = *rep_sect.find_field(model_id); //nuovo campo TReport_field* new_field = (TReport_field*)rep_field.dup(); //lo aggiunge alla sezione rep_sect.add(new_field); //gli da' l'id (e' il terzultimo campo) TReport_section& b1 = section('B', 1); const int body_fields_number = b1.items(); TReport_field& fld_costi = b1.field(body_fields_number - 3); new_field->set_id(fld_costi.id()); //posiziona tutti i campi della sezione for (int i = 0; i < rep_sect.items(); i++) { //c'e' il campo con il mio numero (id) in questa sezione? TReport_field& brock = rep_sect.field(i); if (brock.id() >= model_id) { //se c'e' cerco nel body il mio omonumero; se lo trovo mi allineo come lui //Es.: campi testata di pagina compaiono e si allineano in base ai campi body (fase,cdc ecc.) TReport_field* champ = b1.find_field(brock.id()); if (champ != NULL) brock.set_column(champ->get_rect().left()); } } } int TCRPA_report::show_hide_left_column(const bool show_fld, TReport_field* fld, int x0) { if (fld != NULL) { if (show_fld) { fld->set_column(x0); x0 = fld->get_rect().right(); } else fld->deactivate(); } return x0; } //metodo per il riempimento e lo spostamento dei campi dinamici void TCRPA_report::offset_and_fill_columns(TReport_section& rep_sect, const TString_array& str_arr, const int model_id, const bool show_fasi, const bool show_cdc, const bool show_cms_descr, const bool show_cms_date) { //solo nel caso sia richiesta la sparizione di un campo... if (!show_fasi || !show_cdc || !show_cms_descr || !show_cms_date) { if (rep_sect.type() == 'B') //campi del body { //gestione campi a sinistra del campo modello //la gestione dei campi a sinistra e' guidata dalle scelte utente sulla maschera //primo campo apparibile/scomparibile a sx del campo modello TReport_field* fld_cms_descr = rep_sect.find_field(2); if (fld_cms_descr != NULL) //in caso non esista il campo non deve fare nulla (report riassuntivi x fase/cdc) { TReport_field* fld_dataini = rep_sect.find_field(3); TReport_field* fld_datafine = rep_sect.find_field(4); TReport_field* fld_fase = rep_sect.find_field(5); TReport_field* fld_cdc = rep_sect.find_field(6); TReport_field* fld_perc = rep_sect.find_field(7); int x0 = fld_cms_descr->get_rect().left(); //mostra o no varie colonne a sx del campo esempio x0 = show_hide_left_column(show_cms_descr, fld_cms_descr, x0); //cms_descr x0 = show_hide_left_column(show_cms_date, fld_dataini, x0); //cms_dataini x0 = show_hide_left_column(show_cms_date, fld_datafine, x0); //cms_datafine x0 = show_hide_left_column(show_fasi, fld_fase, x0); //fasi x0 = show_hide_left_column(show_cdc, fld_cdc, x0); //cdc x0 = show_hide_left_column(true, fld_perc, x0); //perc //campo modello rep_sect.find_field(model_id)->set_column(x0); } //if(fld_fase!=NULL.. } else //campi non del body { TReport_section& b1 = section('B', 1); //sistema i campi tipo testata for (int i = 0; i < rep_sect.items(); i++) { //c'e' il campo con il mio numero (id) in questa sezione? TReport_field& brock = rep_sect.field(i); const int id = brock.id(); if (id > 0) { //se c'e' cerco nel body il mio omonumero; se lo trovo mi mostro e allineo come lui //Es.: campi testata di pagina compaiono e si allineano in base ai campi body (fase,cdc ecc.) TReport_field* champ = b1.find_field(id); if (champ != NULL) { brock.activate(champ->active()); brock.set_column(champ->get_rect().left()); } } //if(id>0.. } //for(int i=0;... } //else di if(rep_sect.type()=='B'... } //if(!show_fasi||!show_cdc... TReport_field& rep_field = *rep_sect.find_field(model_id); //prende il rettangolo del campo modello.. const TReport_rct& rep_field_rect = rep_field.get_rect(); //deve spostare i campi a destra della colonna modello //si memorizza i campi a destra del campo modello per poterli mettere a destra di tutti.. //..i campi che saranno generati TPointer_array campi_a_destra; for (int j = 0; j < rep_sect.items(); j++) { const TReport_field& campo = rep_sect.field(j); //solo i campi con un identificatore vanno spostati; gli altri sono parte dello sfondo if (campo.id() > model_id) { const TReport_rct& rct = campo.get_rect(); //se il campo e' a destra del modello lo aggiunge all'array dei campi_a_destra if (rct.left() >= rep_field_rect.right()) campi_a_destra.add(campo); } } //duplica il campo modello e riempie i duplicati con i valori degli array //serve il tipo di sezione poiche' gli header vanno trattati diversamente dai body const char sect_type = rep_sect.type(); //ciclo su tutti gli elementi dell'array con i valori da settare nei nuovi campi for (int i = 0; i < str_arr.items(); i++) { //crea il nuovo campo i-esimo, copia del modello, spostato a destra rispetto al precedente (i-1)esimo.. //.., con id(i) = id(i-1) + 1 TReport_field* new_field = i == 0 ? &rep_field : (TReport_field*)rep_field.dup(); if (i > 0) { rep_sect.add(new_field); new_field->set_pos(rep_field_rect.left() + rep_field_rect.width() * i, rep_field_rect.top()); new_field->set_id(rep_field.id() + i); } switch (sect_type) { case 'H': //gli header devono stampare l'intestazione { new_field->set_picture(str_arr.row(i)); } break; case 'B': //i body devono stampare i valori e sommarli ai totali nei footer { new_field->set_field(str_arr.row(i)); TString ps = "MESSAGE ADD,F3."; ps << new_field->id(); if (find_section('F', 4) != NULL) ps << "|ADD,F4." << new_field->id(); new_field->set_postscript(ps); } break; case 'F': //i footer devono calcolarsi i totali; ma i footer di totale fasi (4) non devono.. //..fare assolutamente nulla! if (rep_sect.level() > 0 && rep_sect.level() < 4) { //crea il campo sul report con tanto di id,postscript ecc... new_field->set_field(""); switch (rep_sect.level()) { case 1: { //caso particolare del footer di report con i totali alla Adolf! //Dalla matematica secondo Adolf: //(a) TotGen = TotCmsNor + TotCmsSupp //(b) DiffGen = TotCmsSupp - TotCmsNor //->(c) DiffGen = TotGen - 2*TotCmsNor //i campi del totale generale si sommano ai campi delle differenze di Adolf /**CAZZONE** tentata per utilizzare la (c) ma non funziona:questi non servono a una ceppa di minchia new_field->set_field(""); TString ps = "MESSAGE ADD,F"; ps << (rep_sect.level()) << '.' << (new_field->id() + 200); new_field->set_prescript(ps);*/ //sub_new_field e' il campo SOTTO il new_field che appare solo nei totali di sezione 1 (F1) //e' il campo che va nella riga delle Differenze /*TReport_field* sub_new_field = (TReport_field*)new_field->dup(); rep_sect.add(sub_new_field); sub_new_field->offset(TPoint(0, 250)); sub_new_field->set_id(new_field->id() + 200); sub_new_field->set_groups("90"); sub_new_field->set_prescript("");*/ } break; case 2: { //ogni campo di footer F2 deve sommarsi a quello piu' esterno F1 TString ps = "MESSAGE ADD,F"; ps << (rep_sect.level() - 1) << '.' << new_field->id(); //in caso di Commesse Supporto (LEVEL=4) il totale si deve sommare nelle differenze generali ps << "\n#101 @\n"; ps << "4 = IF\n"; ps << " MESSAGE ADD,F1." << (new_field->id() + 200) << "\n"; ps << "THEN"; //setta il postscript al new_field new_field->set_postscript(ps); //SUB_new_field, ovvero gestione dei campi adolfici dei totali e delle differenze //Gestione totali delle commesse normali (Adolf!) //Alla fine di tutte le 4 sezioni di commesse normali ci va il totale delle medesime; questo.. //..totale va stampato prima della sezione con le commesse di appoggio //sub_new_field e' il campo SOTTO il new_field che appare solo nei totali di sezione 2 (F2) //e' il campo con il totale delle commesse normali TReport_field* sub_new_field = (TReport_field*)new_field->dup(); rep_sect.add(sub_new_field); sub_new_field->offset(TReport_size(0, 250)); sub_new_field->set_id(new_field->id() + 200); sub_new_field->set_groups("90"); sub_new_field->set_postscript(""); //il totale delle commesse normali si sottrae nelle differenze generali TString ps_diff; //ps_diff << "#THIS @\n2\n*\n!\n"; **CAZZONE** tentata per applicare la (c);non funzia ps_diff << "MESSAGE SUB,F1." << sub_new_field->id(); sub_new_field->set_postscript(ps_diff); } break; case 3: { //ogni campo di footer F3 deve sommarsi a quello piu' esterno F2 TString ps = "MESSAGE ADD,F"; ps << (rep_sect.level() - 1) << '.' << new_field->id(); //deve anche sommarsi al totale delle Commesse Normali (che viene stampato al passaggio tra.. //..LEVEL=3 e LEVEL=4) ps << "\nMESSAGE ADD,F2." << (new_field->id() + 200); //setta il postscript al new_field new_field->set_postscript(ps); } break; default: break; } //switch(rep_sect.level()) } break; default: break; } //switch (sect_type) } //for(inti=0;idup(); rep_sect.add(sub_new_field_margine); sub_new_field_margine->offset(TReport_size(0, 250)); sub_new_field_margine->set_id(369); sub_new_field_margine->set_groups("90"); sub_new_field_margine->set_postscript(""); } //ordina i campi davvero sul report per id rep_sect.sort(); } bool TCRPA_report::generate_columns (TString_array& codici, TString_array& testate, const int model_id, const bool show_fasi, const bool show_cdc, const bool show_cms_descr, const bool show_cms_date) { //sezioni del report da modificare TReport_section& b1 = section('B', 1); //controllo dell'esistenza dei campi modello da replicare e loro duplicazione e riempimento! TReport_field* b1_model = b1.find_field(model_id); if (b1_model == NULL) return false; offset_and_fill_columns(b1, codici, model_id, show_fasi, show_cdc, show_cms_descr, show_cms_date); //testate //la testata di pagina deve invece riempire le intestazioni delle colonne generate TReport_section& h0 = section('H', 0); TReport_field* h0_model = h0.find_field(model_id); if (h0_model == NULL) warning_box(TR("Manca l'intestazione della colonna modello (H0.%d)"),model_id); else offset_and_fill_columns(h0, testate, model_id, show_fasi, show_cdc, show_cms_descr, show_cms_date); //le testate di sezione devono resettare i campi totale dei corrispondenti footers for (int j = 4; j > 0; j--) { TReport_section& head = section('H', j); if (head.items() > 0) { TString ps(256); ps = "MESSAGE "; //i campi dei totali da resettare sono tanti quante le colonne generate //k=0 per includere la colonna 69!!! usata nel caso i ricavi siano solo di livello 1 (depth=1) for (int k = 0; k <= codici.items(); k++) { if (k > 0) ps << '|'; ps << "RESET,F" << head.level() << '.' << (k+model_id); } head.set_prescript(ps); } } //footers for (int i = find_max_level('F') - 1; i > 0; i--) { TReport_section& foot = section('F', i); TReport_field* foot_model = foot.find_field(model_id); if (foot_model == NULL) warning_box(TR("Manca la colonna modello (F%d.%d)"), i, model_id); else offset_and_fill_columns(foot, codici, model_id, show_fasi, show_cdc, show_cms_descr, show_cms_date); } //gestione della sezione con i totali di commessa (solo se esiste, visto che non c'e' in tutti i report) TReport_section* f4 = find_section('F', 4); if (f4 != NULL) offset_and_fill_sectionf4(*f4, model_id); #ifdef DBG save("cazzone.rep"); #endif return true; } TCRPA_report::TCRPA_report (const char* rep_name, const TString& prefix, const int depth, const bool show_fasi, const bool show_cdc, const bool show_cms_descr, const bool show_cms_date) { //che report usare? load (rep_name); //array contenenti i conti analitici e le loro descrizioni di testata che diventeranno.. //.colonne del report dopo lungo e periglioso travaglio TString_array codici, testate; //per prima cosa si deve analizzare la struttura del piano conti.. //..da stampare fino al livello richiesto! analize_pconana_structure (prefix, depth, codici, testate); //poi vanno generate le colonne del report corrispondenti alla struttura analizzata generate_columns (codici, testate, 69, show_fasi, show_cdc, show_cms_descr, show_cms_date); }