Autore Topic: [RISOLTO]Problema con PdfWriter  (Letto 2469 volte)

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
[RISOLTO]Problema con PdfWriter
« il: 28 Dicembre 2009, 14:24:34 »
Ciao a tutti,
Ho un problema con PdfWriter.
Allora, all'inizio mi ero costruito il report usando il comando "ME.Cell" per inserire i campi in ogni riga, ecco una parte di codice:
Codice: [Seleziona]

    IF MyRS.Available = TRUE THEN    
          FOR EACH MyRS                                    
                  ME.Cell(10, 5, MyRS!quantita, TRUE, 0, "L", FALSE)
                  ME.Cell(32, 5, MyRS!codice, TRUE, "L", FALSE)
                  ME.Cell(108, 5, MyRS!descrizione, TRUE, "L", FALSE)
                  ME.Cell(20, 5, MyRS!prezzo, TRUE, 0, "R", FALSE)                        
           ME.Ln()
          NEXT
    ENDIF

Praticamente con queste 4 Cell crea una riga con i 4 campi interessati. Tutto ok, solo che la lunghezza del campo descrizione può essere più lungo dello spazio destinato. Allora per il campo descrizione ho provato a usare multicell.
Il campo con multicell si ingrandisce in altezza e quindi il testo va a capo. Succede però questo: se prima con Cell ogni campo si "appoggiava" a dx del campo precedente fino al comando ME.Ln() (creando la riga ordinata) con multicell il campo successivo va a caporiga. Quindi avevo risolto così: ad ogni cella e multicella davo le coordinate con SetXY, ecco una parte di codice:
Codice: [Seleziona]

   IF MyRS.Available = TRUE THEN    
          FOR EACH MyRS
               mag_y = 0 ' rimetto sempre la maggiorazione y a 0
               IF ME.GetStringWidth(MyRS!descrizione) > 100 THEN
                mag_y = 5 ' maggioro la maggiorazione y di 1 riga (5 è la mia altezza riga)
               ENDIF
               IF ME.GetStringWidth(MyRS!descrizione) > 200 THEN
                mag_y = 10 ' maggioro la maggiorazione y di 2 righe (5 è la mia altezza riga)
               ENDIF                                    

                  ME.SetXY(10, pos_y)  
                  ME.Cell(10, 5, MyRS!quantita, TRUE, 0, "L", FALSE)
                  ME.SetXY(20, pos_y)  
                  ME.Cell(32, 5, MyRS!codice, TRUE, "L", FALSE)
                  ME.SetXY(52, pos_y)              
                  ME.MultiCell(108, 5, MyRS!descrizione, TRUE, "L", FALSE)
                  ME.SetXY(160, pos_y)  
                  ME.Cell(20, 5, MyRS!prezzo, TRUE, 0, "R", FALSE)
                         
           ME.Ln()
           pos_y = (ME.GetY() + mag_y)
          NEXT
    ENDIF

..spostando le coordinate anche di una riga o 2 a seconda della lunghezza del testo descrizione, ricavato con il comando GetStringWidth.
E funzionava all meraviglia...finchè non ho fatto un report con più di una pagina.
Praticamente la prima pagina la fà correttamente, poi incasina tutto.
Fà questo, ad esempio ho un report di un'intera pagina più una riga. Non crea 2 pagine ma 5. La prima è corretta, la seconda (che dovrebbe esserci solo 1 riga) ho solo il campo quantità, la terza il campo codice, la quarta il campo descizione, la quinta il campo prezzo.
Spero di essere riuscito a spiegarmi bene..
Come potrei risolvere questo problema?
Ciao grazie

Offline dex

  • Gran Maestro dei Gamberi
  • *****
  • Post: 872
    • Mostra profilo
Re: Problema con PdfWriter
« Risposta #1 il: 28 Dicembre 2009, 22:50:03 »
ciao golia
vedo che sei sempre alle prese con il tuo progetto.

il report che stai cercando di fare è una fattura, un ddt oppure un ordine?

se si tratta di uno di questi casi, non ho sperimentato multicel ma ho creato un report fatture multipagina che mi riporta per ogni pagina intestazione dati tutti i campi e numerazione pagina, con il riepilogo dei totali sull'ultima pagina.

se ti può servire ti posto la classe.

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
Re: Problema con PdfWriter
« Risposta #2 il: 28 Dicembre 2009, 23:13:18 »
E' un ordine, le fatture non le ho ancora fatte. PdfWriter va a capo pagina da solo, almeno usando cell sono sicuro perchè avevo provato. Con multicell mi scombina tutto alla seconda pagina..
Come hai risolto se una stringa è più lunga dello spazio destinato con cell?

Citazione
se ti può servire ti posto la classe.

 :-) si grazie, anche perchè sono in panne  :cry:
Ciao grazie

Offline dex

  • Gran Maestro dei Gamberi
  • *****
  • Post: 872
    • Mostra profilo
Re: Problema con PdfWriter
« Risposta #3 il: 29 Dicembre 2009, 00:51:58 »
non ho fatto il calcolo per non superare lo spazio.
se non sbaglio ci deve essere una funzione per calcolare la lunghezza di una stringa,
tipo:
Codice: [Seleziona]
DIM LunT AS Integer
   
  LunT = GridView1.Font.Width("Colonna Dati")

questo codice dovrebbe calcolare la lunghezza del testo nella griglia, prova ad usarlo con una variabile.

in allegato ti posto il report per le fatture che puoi tranquillamente adeguare sia agli ordini che ai ddt.

ps per le variabili capirai da solo dove devi cambiare, per quelle che cominciano per M1. sono variabili globali.

in allegato alla classe ho messo un pdf generato con questa classe

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
Re: Problema con PdfWriter
« Risposta #4 il: 29 Dicembre 2009, 02:02:14 »
Ti ringrazio tantissimo, me la guardo poi ti faccio sapere

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
Re: Problema con PdfWriter
« Risposta #5 il: 29 Dicembre 2009, 15:06:22 »
Per calcolare la lunghezza della stringa c'è una funzione in PdfWtriter "ME.GetStringWidth".
Ho guardato la tua classe, più o meno è come faccio io (mi è piaciuto il numero di pagina con la scritta segue>>).
Ma mi sembra di avere capito che non hai il testo che và a caporiga.

Me.Multicell funziona benissimo, se crei una cella larga 100, multicell ci scrive dentro il testo e crea tante righe a seconda della lunghezza della stringa.
C'è solo il problema che non fà come Me.cell che salva la posizione x e y per la cella che viene dopo, và a caporiga.

Mi sono guardato bene PdfWriter e ho confrontato le funzioni Cell e Multicell. Ho visto appunto che Cell passa il valore per la posizione x e y mentre Multicell no. Non so se c'è un motivo perchè MD9327 ha fatto così..(Si potrebbe sdoppiare la funzione e fare Multicell2) Ho provato a metterci le mani a Multicell e qulacosa ho fatto.
Codice: [Seleziona]

'$x = $lMargin  ''''Questa è l'ultima riga della funzione Multicell
$y -= h
$x += w

Ho inserito le ultime 2 righe e disattivato $x = $lMargin.
Le ultime 2 righe le ho ricavate da Cell.
Adesso il valore x viene passato correttamente come Cell, il valore y viene passato correttamente solo se la cella non diventa più grande, cioè non va a caporiga (posto sotto un'immagine). Praticamente mi basterebbe il valore di quante righe crea multicell per risolvere il tutto, cioè così
Codice: [Seleziona]
$y -= (h * n°righe)

Nell'immagine che ho allegato vedete le situazioni che ho segnato con la freccia rossa. Quando multicell crea più righe, il valore y passato è sempre solo del valore di 1 riga, quindi non allinea in alto la prossima cella.
...Scusate, stanotte questo non mi ha fatto dormire :-(
Ciao a tutti

Offline dex

  • Gran Maestro dei Gamberi
  • *****
  • Post: 872
    • Mostra profilo
Re: Problema con PdfWriter
« Risposta #6 il: 29 Dicembre 2009, 21:55:10 »
sorry

nel mio caso non mi sono nemmeno posto il caporiga in quanto superfluo per le mie fatture.
devi contattare md, solo lui può darti la soluzione.

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
Re: Problema con PdfWriter
« Risposta #7 il: 29 Dicembre 2009, 23:14:15 »
C'è l'ho fatta !!!! :-D  8-)
Ho creato (copiando le funzioni di md) 3 funzioni nuove e funzionano perfettamente.
Controllo il tutto e posto

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
Re: Problema con PdfWriter
« Risposta #8 il: 29 Dicembre 2009, 23:25:10 »
Nella classe PdfWriter ho aggiunto:

Sopra nelle dichiarazioni:
Codice: [Seleziona]

PRIVATE $lasthmulti AS Integer


In fondo queste 3 funzioni
Codice: [Seleziona]

PUBLIC SUB Cell2(w AS Float, OPTIONAL h AS Float = 0, OPTIONAL txt AS String = "", OPTIONAL border AS Variant = FALSE, OPTIONAL ln AS Integer = 0, OPTIONAL align AS String = "", OPTIONAL fill AS Boolean = FALSE, OPTIONAL slink AS String = "")
  DIM k, x, y, ws, dx, wmax, wlink AS Float
  DIM s, op, txt2 AS String
  'Output a cell
  k = $k

  IF (w = 0) THEN w = $w - $rMargin - $x
  s = ""
  IF (IsBoolean(border)) THEN
    IF (fill OR border) THEN
      op = IIf(fill, IIf(border, "B", "f"), "S")
      s = _stringFloat($x * k, "0.00") & " " &
          _stringFloat(($h - $y) * k, "0.00") & " " &
          _stringFloat(w * k, "0.00") & " " &
          _stringFloat(- h * k, "0.00") & " re " & op & " "
    END IF
  ELSE IF (IsString(border)) THEN
    x = $x
    y = $y
    IF (InStr(border, "L")) THEN
      s &= _stringFloat(x * k, "0.00") & " " &
           _stringFloat(($h - y) * k, "0.00") & " m " &
           _stringFloat(x * k, "0.00") & " " &
           _stringFloat(($h - (y + h)) * k, "0.00") & " l S "
    END IF
    IF (InStr(border, "T")) THEN
      s &= _stringFloat(x * k, "0.00") & " " &
           _stringFloat(($h - y) * k, "0.00") & " m " &
           _stringFloat((x + w) * k, "0.00") & " " &
           _stringFloat(($h - y) * k, "0.00") & " l S "
    END IF
    IF (InStr(border, "R")) THEN
      s &= _stringFloat((x + w) * k, "0.00") & " " &
           _stringFloat(($h - y) * k, "0.00") & " m " &
           _stringFloat((x + w) * k, "0.00") & " " &
           _stringFloat(($h - (y + h)) * k, "0.00") & " l S "
    END IF
    IF (InStr(border, "B")) THEN
      s &= _stringFloat(x * k, "0.00") & " " &
           _stringFloat(($h - (y + h)) * k, "0.00") & " m " &
           _stringFloat((x + w) * k, "0.00") & " " &
           _stringFloat(($h - (y + h)) * k, "0.00") & " l S "
    END IF
  END IF
  IF (txt <> "") THEN
    SELECT CASE align
    CASE "R"
      dx = w - $cMargin - ME.GetStringWidth(txt)
    CASE "C"
      dx = (w - ME.GetStringWidth(txt)) / 2
    CASE "FJ" 'Justify
      'Set word spacing
      wmax = (w - 2 * $cMargin)
      $ws = (wmax - ME.GetStringWidth(txt)) / (Split(txt, " ").Count - 1)
      _out(_stringFloat($ws * $k, "0.000") & " Tw")
      dx = $cMargin
    DEFAULT
      dx = $cMargin
    END SELECT
    IF ($ColorFlag) THEN s &= "q " & $TextColor & " "
    txt2 = Replace(Replace(Replace(txt, "\\", "\\\\"), "(", "\\("), ")", "\\)")
    txt2 = Conv(txt2, "UTF-8", "ISO-8859-1") ''''''aggiunta
    s &= "BT " & _stringFloat(($x + dx) * k, "0.00") & " " &
                 _stringFloat(($h - ($y + 0.5 * h + 0.3 * $FontSize)) * k, "0.00") & " Td (" & txt2 & ") Tj ET"
    IF ($underline) THEN s &= " " & _dounderline($x + dx, $y + 0.5 * h + 0.3 * $FontSize, txt)
    IF ($ColorFlag) THEN s &= " Q"
    'IF (slink) THEN ME.Link($x + dx, $y + 0.5 * h - 0.5 * $FontSize, ME.GetStringWidth(txt), $FontSize, slink)
    IF (slink) THEN
      IF (align = "FJ") THEN
        wlink = wmax
      ELSE
        wlink = ME.GetStringWidth(txt)
      END IF
      ME.Link($x + dx, $y + 0.5 * h - 0.5 * $FontSize, wlink, $FontSize, slink)
    END IF
  END IF
  IF (s) THEN _out(s)
  IF (align = "FJ") THEN
    'Remove word spacing
    _out("0 Tw")
    $ws = 0
  END IF
  $lasth = h
  IF (ln > 0) THEN
    'Go to next line
    $y += h
    IF (ln = 1) THEN $x = $lMargin
  ELSE
    $x += w
  END IF
END

PUBLIC SUB MultiRiga(w AS Float, h AS Float, txt AS String, OPTIONAL border AS Variant = FALSE, OPTIONAL align AS String = "J", OPTIONAL fill AS Boolean = FALSE)
  DIM cw AS Integer[]
  DIM wmax AS Float
  DIM s, b, b2, c AS String
  DIM nb, sep, i, j, l, ns, nl, ls AS Integer
  DIM numeroriga AS Integer
  DIM salva$y AS Integer
  DIM hriga AS Integer
 
  salva$y = $y
  numeroriga = 0
  'Output text with automatic or explicit line breaks
  cw = $CurrentFont["cw"]
  IF (w = 0) THEN w = $w - $rMargin - $x
  wmax = (w - 2 * $cMargin) * 1000 / $FontSize
  s = Replace(txt, "\r", "")
  nb = Len(s)
  IF (nb > 0) AND IF (Mid(s, nb, 1) = "\n") THEN DEC nb
  b = 0
  IF (IsBoolean(border) OR IsInteger(border)) THEN
    IF (border) THEN
      border = "LTRB"
      b = "LRT"
      b2 = "LR"
    END IF
  ELSE IF (IsString(border)) THEN
    b2 = ""
    IF (InStr(border, "L")) THEN b2 &= "L"
    IF (InStr(border, "R")) THEN b2 &= "R"
    b = IIf(InStr(border, "T"), b2 & "T", b2)
  END IF
  sep = -1
  i = 1
  j = 1
  l = 0
  ns = 0
  nl = 1
  WHILE (i <= nb)
 
    'Get next character
    c = Mid(s, i, 1)
    IF (c = "\n") THEN
      'Explicit line break
      IF ($ws > 0) THEN
        $ws = 0
        _out("0 Tw")
      END IF
      numeroriga += 1
      ME.Cell2(w, h, Mid(s, j, i - j), b, 2, align, fill)
      INC i
      sep = -1
      j = i
      l = 0
      ns = 0
      INC nl
      IF (IsBoolean(border) OR IsInteger(border)) THEN
        IF (border AND nl = 2) THEN b = b2
      ELSE IF (IsString(border)) THEN
        IF (NOT IsNull(border) AND nl = 2) THEN b = b2
      END IF
      CONTINUE
    END IF
    IF (c = " ") THEN
      sep = i
      ls = l
      INC ns
    END IF
    l += cw[Asc(c)]
    IF (l > wmax) THEN
      'Automatic line break
      IF (sep = -1) THEN
        IF (i = j) THEN INC i
        IF ($ws > 0) THEN
          $ws = 0
          _out("0 Tw")
        END IF
        numeroriga += 1
        ME.Cell2(w, h, Mid(s, j, i - j), b, 2, align, fill)
      ELSE
        IF (align = "J") THEN
          $ws = IIf(ns > 1, (wmax - ls) / 1000 * $FontSize / (ns - 1), 0)
          _out(_stringFloat($ws * $k, "0.000") & " Tw")
        END IF
        numeroriga += 1
        ME.Cell2(w, h, Mid(s, j, sep - j), b, 2, align, fill)
        i = sep + 1
      END IF
      sep = -1
      j = i
      l = 0
      ns = 0
      INC nl
      IF (IsBoolean(border) OR IsInteger(border)) THEN
        IF (border AND nl = 2) THEN b = b2
      ELSE IF (IsString(border)) THEN
        IF (NOT IsNull(border) AND nl = 2) THEN b = b2
      END IF
    ELSE
      INC i
    END IF
  WEND
  'Last chunk
  IF ($ws > 0) THEN
    $ws = 0
    _out("0 Tw")
  END IF
  IF (IsString(border)) THEN
    IF (NOT IsNull(border) AND InStr(border, "B")) THEN b &= "B"
  END IF
  ME.Cell2(w, h, Mid(s, j, i - j), b, 2, align, fill)

  IF numeroriga = 0 THEN
  hriga = h
  ELSE IF numeroriga = 1 THEN
  hriga = (h * 2)
  ELSE IF numeroriga = 2 THEN
  hriga = (h * 3)
  ELSE IF numeroriga = 3 THEN
  hriga = (h * 4)
  ELSE IF numeroriga = 4 THEN
  hriga = (h * 5)  
  ENDIF

  $lasthmulti = Max($lasthmulti, hriga)
 
   $y = salva$y

  $x += w

END

PUBLIC SUB Lnm()
  'Line feed; default value is last cell height
  DIM k, x, y, ws, dx, wmax, wlink AS Float
    IF ($y + $lasthmulti > $PageBreakTrigger AND NOT $InFooter AND AcceptPageBreak()) THEN
    'Automatic page break
    x = $x
    ws = $ws
    IF (ws > 0) THEN
      $ws = 0
      _out("0 Tw")
    END IF
    ME.AddPage($CurOrientation)
    $x = x
    IF (ws > 0) THEN
      $ws = ws
      _out(_stringFloat(ws * k, "0.000") & " Tw")
    END IF
  END IF
  $x = $lMargin
  $y += $lasthmulti
  $lasthmulti = 0
END


Poi nella classe di stampa
Codice: [Seleziona]

          FOR EACH MyRS
              ME.MultiRiga(10, 5, MyRS!quantita, TRUE, "L", FALSE)
              ME.MultiRiga(32, 5, MyRS!codice, TRUE, "L", FALSE)
              ME.MultiRiga(108, 5, MyRS!descrizione, TRUE, "L", FALSE)
              ME.MultiRiga(20, 5, MyRS!prezzo, TRUE, "R", FALSE)  
              ME.MultiRiga(20, 5, MyRS!totale, TRUE, "R", FALSE)
          ME.Lnm()
          NEXT

Attenzione nella stessa riga usare sempre Multiriga altrimenti non funziona e cambiare riga con ME.Lnm() non ME.Ln(), poi sotto si può continuare con qualsiasi funzione di PdfWriter.

PDFWRITER È TROPPO BELLO!!!!!  GRAZIE MD9327
:pint:  :pint:

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
Re: Problema con PdfWriter
« Risposta #9 il: 29 Dicembre 2009, 23:32:49 »
Guardate che meraviglia :-D  :-)
e funziona anche nelle pagine successive
« Ultima modifica: 15 Aprile 2010, 14:23:23 da Golia »

Offline Ceskho

  • Amministratore
  • Senatore Gambero
  • *****
  • Post: 3.778
  • Vi Veri Veniversum Vivus Vici
    • Mostra profilo
    • Pagina Personale
Re: [RISOLTO]Problema con PdfWriter
« Risposta #10 il: 30 Dicembre 2009, 00:50:48 »
Non si possono impostare anche le altre celle della stessa altezza?

Mi spiego meglio: il campo in cui c'è 1 è più piccolo rispetto a quello dove c'è scritto CODICE...sarebbe meglio renderli più stile tabella secondo me..

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
Re: [RISOLTO]Problema con PdfWriter
« Risposta #11 il: 30 Dicembre 2009, 01:30:39 »
Si sarebbe più bello ho anche cercato di capire come disegna le lineee, ma..niente.
Comunque mi sembra già di toccare la luna così, poi se md ci legge magari ci fà un pensierino :-D
Ciao

Offline dex

  • Gran Maestro dei Gamberi
  • *****
  • Post: 872
    • Mostra profilo
Re: [RISOLTO]Problema con PdfWriter
« Risposta #12 il: 31 Dicembre 2009, 01:37:35 »
congratulazioni, carina l'idea delle multicell.

mi è venuta un'idea (non verificata), e se fosse possibile leggere il numero delle righe per ogni multicella?

nelle multicelle + piccole basterebbe aggiungere del testo vuoto fino a farle avere le stesse righe.

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
Re: [RISOLTO]Problema con PdfWriter
« Risposta #13 il: 31 Dicembre 2009, 06:07:30 »
si ci stavo pensando anch'io di fare così, ma stanotte....mah forse me lo sono sognato :-D  e sono saltato giù dal letto.
Guarda che facile che è la soluzione
Nuova funzione per PdfWriter
Codice: [Seleziona]
PUBLIC SUB MultiRect(w1 AS Float, w2 AS Float, w3 AS Float, w4 AS Float, w5 AS Float, w6 AS Float, w7 AS Float)  
  IF w1 > 0 THEN
  ME.Rect($lMargin, $y, w1, $lasthmulti, "")
  ENDIF
  IF w2 > 0 THEN
  ME.Rect($lMargin + w1, $y, w2, $lasthmulti, "")
  ENDIF
  IF w3 > 0 THEN
  ME.Rect($lMargin + w1 + w2, $y, w3, $lasthmulti, "")
  ENDIF
  IF w4 > 0 THEN
  ME.Rect($lMargin + w1 + w2 + w3, $y, w4, $lasthmulti, "")
  ENDIF
  IF w5 > 0 THEN
  ME.Rect($lMargin + w1 + w2 + w3 + w4, $y, w5, $lasthmulti, "")
  ENDIF
  IF w6 > 0 THEN
  ME.Rect($lMargin + w1 + w2 + w3 + w4 + w5, $y, w6, $lasthmulti, "")
  ENDIF
  IF w7 > 0 THEN
  ME.Rect($lMargin + w1 + w2 + w3 + w4 + w5 + w6, $y, w7, $lasthmulti, "")
  ENDIF  
END

e nella classe stampa la scrivo così
Codice: [Seleziona]
FOR EACH MyRS
 ME.MultiRiga(10, 5, MyRS!quantita, FALSE, "L", FALSE)  
 ME.MultiRiga(32, 5, MyRS!codice, FALSE, "L", FALSE)            
 ME.MultiRiga(108, 5, MyRS!descrizione, FALSE, "L", FALSE)
 ME.MultiRiga(20, 5, MyRS!prezzo, FALSE, "R", FALSE)
 ME.MultiRiga(20, 5,  MyRS!totale, FALSE, "R", FALSE)

 ME.MultiRect(10, 32, 108, 20, 20, 0, 0)

 ME.Lnm()
NEXT
Attenzione disattivare con FALSE la funzione border di multiriga (come esempio)
 

:-) guardate adesso che meraviglia
« Ultima modifica: 15 Aprile 2010, 14:25:43 da Golia »

Offline Golia

  • Senatore Gambero
  • ******
  • Post: 1.298
  • no xe mai massa tardi
    • Mostra profilo
Re: [RISOLTO]Problema con PdfWriter
« Risposta #14 il: 31 Dicembre 2009, 06:35:23 »
Adesso speriamo di tirare fino a mezzanotte...mi sono alzato troppo presto :lol:

Intanto auguro buon anno a tutti  :2birre:  :2birre:  :2birre:  :pint:  :pint:  :pint:  e non bevete troppo stasera :lol:  :lol: