ziopex / plsql-utils

Automatically exported from code.google.com/p/plsql-utils
0 stars 0 forks source link

Pdf -- new functions #5

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Update:

The conversion to clob looks like it’s working pretty well.   

This one item was overlooked, make the subtype txt large:

subtype txt         is varchar2(32767)

Also I overloaded the output function to return a blob.

Additionaly, I converted the NbLines function from php to plsql.  This makes 
multicell page break correctly.  

Finally I created custom th and td functions so that I could create tables with 
mulitcell with proper page breaks.  

See procedure newstuff1_demo to see how it works. 

Brian
brian@databaseknowledge.com

Here's all of the new functions, add Add these to the pdf package:

---- in declare section: 

type headerRec is record ( 
    width       number,
    label       varchar2(200),
    colspan     number,
    colspanwidth    number,
    fontFamily  varchar2(15),
    fontWeight  varchar2(1),
    fontSize    varchar2(10),
    align       varchar2(10),
    lineheight  number,
    data        varchar2(10000)
                    );

type headerArray is table of headerRec index by pls_integer;

headers     headerArray;
tdCt        pls_integer;

----- here's the code:

function Output     return blob is
   v_doc blob;      
   v_blob blob;
   v_clob clob;
   v_in pls_integer;
   v_out pls_integer;
   v_lang pls_integer;
   v_warning pls_integer;
   v_len pls_integer;
begin

     if state < 3 then
          ClosePDF();
     end if;

   dbms_lob.createtemporary(v_blob, false, dbms_lob.session);
   dbms_lob.createtemporary(v_doc, false, dbms_lob.session);

    v_in            := 1;
    v_out       := 1;
    v_lang      := 0;
    v_warning := 0;
    v_len       := dbms_lob.getlength(pdfDoc);
    dbms_lob.convertToBlob(v_blob, pdfDoc, v_len, v_in, v_out, dbms_lob.default_csid, v_lang, v_warning);
    dbms_lob.append(v_doc, v_blob);

    return v_doc;       

end Output;

function NbLines(win number, txt varchar2) return number is

    wmy     number := win;
    wMax    number ;
    nb      number;

    cw      CharSet;
    s       varchar2(32000);

    sep number  := -1;
--  i number        := 0;
--  j number        := 0;
  i number      := 1;
  j number      := 1;
  l number      := 0;
  ns number     := 0;
  nl number     := 1;

  c  word;

begin

    cw := CurrentFont.cw;

    if wmy = 0 then
        wmy := wmy - rMargin - x;
    end if;

  wmax  := (wmy-2*cMargin)*1000/FontSize;
    s           := wpdf.str_replace(CHR(13),'',txt);
  nb        := strlen(s);

    if(nb > 0 and substr(s,-1) = CHR(10) ) then
        nb := nb - 1;
    end if;

    while(i <= nb) loop
        c := substr(s,i,1);
        if(c = CHR(10)) then
            i := i + 1;
            sep := -1;
            j := i;
            l := 0;
            nl := nl + 1;
            goto endofloop;
    end if;

    if(c = ' ') then
      sep := i;
        end if;

        l := l + cw(c);

        if l > wmax then
            if sep = -1 then
        if i = j then
          i := i + 1;
        end if;
            else
        i := sep + 1;
            end if;

      sep := -1;
      j := i;
      l := 0;
      nl := nl + 1;
        else
        i := i + 1;
        end if;

        <<endofloop>>
    null;
  end loop;     

    return nl;

end;

procedure CheckPageBreak(h number) is
begin

    if GetY()+h > PageBreakTrigger then
       AddPage(CurOrientation);
    end if;

end;

function extract(token varchar2, style varchar2) return varchar2 is

    loc pls_integer;
  s     pls_integer;
    e       pls_integer;

begin

  loc := instr(style, token);
  if loc = 0 then 
    return null; 
  end if;     

  s := instr(style||':', ':', loc);
  e := instr(style||';', ';', loc);    

  return substr(style||';', s+1, e-s-1); 

end;

procedure th(width number, label varchar2, align varchar2 default 'c') is
    ct number;
begin

    ct                              := headers.count +1;
    headers(ct).width := width; 
    headers(ct).label := label; 

    wpdf.Cell(width,5,label, 0,0,upper(align));

end;

procedure tClear is
    ct number;
begin

    headers.delete;
  tdCt := null;

end;

procedure td(style varchar2, d varchar2) is

    fontFamily      varchar2(15)    := 'Arial';
    fontSize            varchar2(10)    := '8';
    fontWeight      varchar2(10)    := '';
    align                   varchar2(10);
  colspan           number;
    colspanWidth    number  := 0;
    lineHeight      number  := 5.5;

    x           number;
  y         number;

  yAft  number;

    nb                          number;
  nbrLinesMax           number;
  lineHeightMin     number;
    h                               number;

  tdCurrent             number;
    idx                         number;
begin

    if tdCt is null then
      wpdf.SetFont('Arial','',8);
        wpdf.ln(5);
    tdCt            := 0;
  end if;

    if style is not null then

    align           := extract('align', style);
    if align is not null then 
        if align = 'left' then
            align := 'l';
        elsif align = 'right' then
        align := 'r';
      elsif align = 'center' then
        align := 'c';
      else 
        align := 'l'; --null;
      end if;
        end if;

    fontFamily  := nvl(extract('font-family', style),'Arial');
    fontSize        := nvl(extract('font-size', style), '9');
    fontWeight  := extract('font-weight', style);
        if fontWeight = 'bold' then
        fontWeight := 'B';
    end if;

      colspan       := extract('colspan', style);
    lineHeight  := nvl(extract('line-height', style),5.5);

  end if;

    tdCt            := tdCt +1;
  tdCurrent := tdCt;

  if colspan is not null then
      if colspan > headers.count - (tdCt -1) then
        colspan := headers.count - (tdCt -1);
      end if;
    for i in (tdCt)..(tdCt -1 + colspan) loop
        colspanWidth    := colspanWidth + headers(i).width;
    end loop;       
    tdCt := tdCt + colspan;
  else
    colspan             := 1;
    colspanWidth    := headers(tdCt).width;
  end if;

    headers(tdCurrent).fontFamily       := fontFamily;
    headers(tdCurrent).fontSize         := fontSize;
    headers(tdCurrent).fontWeight       := fontWeight;
    headers(tdCurrent).colspan          := colspan;
    headers(tdCurrent).colspanwidth := colspanWidth;
    headers(tdCurrent).align                := upper(align);
    headers(tdCurrent).lineheight       := lineheight;
  headers(tdCurrent).data                   := trim(d);  

  if tdCt >= headers.count then
        nbrLinesMax         := 0;
    lineHeightMin       := 0;
    idx                         := 1;

    while idx <= headers.count loop
        SetFont(headers(idx).fontFamily,headers(idx).fontWeight,headers(idx).fontSize);
      nb := NbLines(headers(idx).colspanWidth, headers(idx).data);
        if nb > nbrLinesMax then
        nbrLinesMax := nb;
      end if;

      if headers(idx).lineHeight > lineHeightMin then
        lineHeightMin   := headers(idx).lineHeight;
      end if;

      idx := idx + headers(idx).colspan;

    end loop;

    h   := lineHeightMin * (nbrLinesMax);

        CheckPageBreak(h);

        idx := 1;
    while idx <= headers.count loop
        x   := getx;
        y   := gety;

        SetFont(headers(idx).fontFamily,headers(idx).fontWeight,headers(idx).fontSize);

            -- this will add borders ... need to create a style for it.
      --Rect(x,y,headers(idx).colspanWidth,h);     
            multiCell(headers(idx).colspanWidth, lineHeightMin, headers(idx).data, 0, headers(idx).align);

      setxy(x + headers(idx).colspanWidth, y);
      idx := idx + headers(idx).colspan;
        end loop;

        wpdf.ln(h);
    tdCt        := 0;
  end if;

end;

procedure newstuff1_demo is 

    b blob;

begin

  fpdf('P','mm','letter');
    AliasNbPages    := '`p';
    SetMargins(10,20,10);
  openpdf;
  SetAutoPageBreak(true);
  AddPage();

    SetFont('Arial','B',8);

    th(40, 'Description', 'l');
    th(10, 'List');
    th(10,  'Qty');
    th(15, 'Ext');

    for z in 1..30 loop

        td('font-size:7.5;', 'Item Number '|| z );
        td('font-size:7.5;align:right', z*2.3);
        td('font-size:7.5;align:center', z-1);
        td('font-size:7.5;align:right', ( z*2.3 * (z-1) ));

    if z = 3 then
        td('line-height:2;font-size:5.2;font-family:Courier;', 'This line has more text and will wrap to the next line which you would think is an easy task.');    
        td('line-height:2;colspan:3;', '');    
    end if;

  end loop;

    td('font-weight:bold;colspan:4;align:right', 'TOTAL QTY:  $'|| 9999.99 );

    ln(5);
    ln(5);

    SetFont('Arial','',7);
    write(5, 'Example of a page break with the multi line cell:');

    ln(5);
    ln(5);

    tClear;
    SetFont('Arial','B',8);
    th(30, 'Col 1', 'l');
    th(15, 'Col 2');

    for z in 1..15 loop

        td('font-size:6;line-height:3;', 'Row '|| z||' this is a wraping row, as it will wrap. '|| z );
        td('font-size:6;align:center;line-height:3;', 'item '|| z*2);

  end loop;

    wpdf.ln(5);

  b := Output;

  htp.init;
  owa_util.mime_header('application/pdf',false);
  htp.print('Content-Length: ' || dbms_lob.getlength(b));
  htp.print('Content-disposition: inline; filename="pdf.pdf"');
  owa_util.http_header_close;
  wpg_docload.download_file(b);

end;

Original issue reported on code.google.com by brian%da...@gtempaccount.com on 1 Sep 2011 at 4:28

GoogleCodeExporter commented 8 years ago
One more thing: 

In GetStringWidth add 3 lines of code after the "begin":

if pstr is null then
   return 0;
end if;

So that it looks like this:

function GetStringWidth(pstr varchar2) return number is
    charSetWidth    CharSet;
    w                       number;
    lg                      number;
    wdth                    number;
    c                       car;
begin

    if pstr is null then
    return 0;
  end if;

.... ... ... keep rest of function as is....

Original comment by brian%da...@gtempaccount.com on 1 Sep 2011 at 4:59

GoogleCodeExporter commented 8 years ago
Will try to incorporate these changes in the next release.

Original comment by thehunge...@gmail.com on 19 Oct 2011 at 5:31

GoogleCodeExporter commented 8 years ago
Your changes don't compile, unless I'm leaving something out. Did you change 
the declaration of pdfDoc from the tclob type?

Original comment by mike...@gmail.com on 8 Jan 2012 at 7:20