PL/SQL package for create PDF
(versione italiana)Some time ago I found this package to create PDF documents directly from PL / SQL. During this time I added some features for the creation of reports and today I wanted to publish my work.
Your comments, bug indication, correction of english, are appreciated.
Thank to Anton Scheffer who made the original package.
Today I've added new features to the procedure query2table, now it accepts blob fields as image and insert it into cell grid, with resizing and alignment, see the NEW POST HERE.
Download my Lastest vesion and documentation Github
.
This example create a PDF with breaking on the first field;
it doesn't need table because it uses random data.
-- Created on 25/06/2014 by VALR declare i INTEGER; v_vFileName VARCHAR2(255); v_vOddColor VARCHAR2(6) := 'd0d0d0'; v_vHeadColor VARCHAR2(6) := 'e0ffff'; v_vOraDir VARCHAR2(50) := 'PDF'; v_vPageProc VARCHAR2(32000); r_Fmt as_pdf3_v5.tp_columns:=as_pdf3_v5.tp_columns(); v_vSQL varchar2(4000); begin v_vFileName := 'Test_as_pf3_v5.pdf'; -- Define Sheet Format as_pdf3_v5.init; as_pdf3_v5.set_page_format('A4'); as_pdf3_v5.set_page_orientation('P'); as_pdf3_v5.set_margins(30, 10, 15, 10, 'mm'); -- Define Header and Footer v_vPageProc := q'[ begin §.set_font('helvetica', 'B', 10 ); §.put_txt('mm', 5, 5, 'Valerio Rossetti'); §.put_txt('mm', 90, 5, 'Data: '); §.set_font('helvetica', 'N', 10); §.put_txt('mm', 115,5, ']'||to_char(sysdate,'dd/mm/yy')||q'['); §.put_txt('mm', 175,5, 'Page #PAGE_NR# of #PAGE_COUNT#'); end; ]'; as_pdf3_v5.set_page_proc(v_vPageProc); --If you use barcode font, remove comment --as_pdf3_v5.load_ttf_font('PDF', 'ean13.ttf', 'CID', TRUE); -- Define column format begin r_fmt.extend(9); i:=1; -- (riga di rottura r_fmt(i).colWidth:=25; r_fmt(i).colLabel:='cod mkt'; r_fmt(i).hFontStyle:='B'; r_fmt(i).hFontSize:=10; r_fmt(i).hAlignment:='C'; r_fmt(i).hAlignVert:='T'; r_fmt(i).tAlignment:='L'; r_fmt(i).tAlignVert:='B'; r_fmt(i).tFontSize:=8; r_fmt(i).tCHeight := 7; r_fmt(i).hCHeight := 7; r_fmt(i).cellRow := 1; i:=i+1;--2 r_fmt(i).colWidth:=20; r_fmt(i).colLabel:='cod_art'; r_fmt(i).hFontStyle:='B'; r_fmt(i).hFontSize:=10; r_fmt(i).hAlignment:='R'; r_fmt(i).hAlignVert:='T'; r_fmt(i).tAlignVert:='T'; --r_fmt(i).offsetX := 0; r_fmt(i).tCHeight := 7; r_fmt(i).hCHeight := 7; i:=i+1;--3 r_fmt(i).colWidth:=22; r_fmt(i).colLabel:='pz imb'; r_fmt(i).hFontStyle:='B'; r_fmt(i).hFontSize:=10; r_fmt(i).hAlignment:='C'; r_fmt(i).hAlignVert:='T'; r_fmt(i).tAlignment:='R'; r_fmt(i).tAlignVert:='M'; i:=i+1;--4 r_fmt(i).colWidth:=12; r_fmt(i).colLabel:='udm V'; r_fmt(i).hFontStyle:='B'; r_fmt(i).hFontSize:=10; r_fmt(i).hAlignment:='C'; r_fmt(i).hAlignVert:='T'; r_fmt(i).tAlignment:='C'; r_fmt(i).tAlignVert:='B'; r_fmt(i).tBorder := as_pdf3_v5.BorderType('TB'); i:=i+1;--5 r_fmt(i).colWidth:=15; r_fmt(i).colLabel:='udm Lt'; r_fmt(i).hFontStyle:='B'; r_fmt(i).hFontSize:=10; r_fmt(i).hAlignment:='C'; r_fmt(i).hAlignVert:='T'; r_fmt(i).tAlignment:='C'; r_fmt(i).tAlignVert:='B'; i:=i+1;--6 r_fmt(i).colWidth:=20; r_fmt(i).colLabel:='prz. vend.'; r_fmt(i).hFontStyle:='B'; r_fmt(i).hFontSize:=10; r_fmt(i).hAlignment:='C'; r_fmt(i).hAlignVert:='T'; r_fmt(i).tAlignment:='R'; r_fmt(i).tAlignVert:='B'; i:=i+1;--7 r_fmt(i).colWidth:=20; r_fmt(i).colLabel:='prz. cost'; r_fmt(i).hFontStyle:='B'; r_fmt(i).hFontSize:=10; r_fmt(i).hAlignment:='C'; r_fmt(i).hAlignVert:='T'; r_fmt(i).tAlignment:='R'; r_fmt(i).tAlignVert:='B'; i:=i+1;--8 r_fmt(i).colWidth:=16; r_fmt(i).colLabel:='margin'; r_fmt(i).hFontStyle:='B'; r_fmt(i).hFontSize:=10; r_fmt(i).hAlignment:='C'; r_fmt(i).hAlignVert:='T'; r_fmt(i).tAlignment:='R'; r_fmt(i).tAlignVert:='B'; r_fmt(i).tBorder := 15; i:=i+1;--9 r_fmt(i).colWidth:=150; r_fmt(i).colLabel:='product descrition'; r_fmt(i).hFontStyle:='B'; r_fmt(i).hFontSize:=10; r_fmt(i).hAlignment:='L'; r_fmt(i).hAlignVert:='T'; r_fmt(i).hCHeight := 8; r_fmt(i).tAlignment:='L'; r_fmt(i).tAlignVert:='C'; r_fmt(i).tFontSize:=8; r_fmt(i).offsetX := 0; r_fmt(i).tCHeight := 8; r_fmt(i).cellRow:=2; r_fmt(i).tBorder := as_pdf3_v5.BorderType('LRBT'); end; v_vSQL := q'[ SELECT cod_mkt, c_art, pcs_imb, udm_vend, udm_list, prz_vend, prz_vend*.8 prz_cost, prz_vend*.2 margin, description from ( SELECT case when rownum <5 then '5201001' else '5201003' end cod_mkt, rownum*1000+rownum*124 c_art, (trunc(rownum/3)+1)*4 pcs_imb, 'N' udm_vend, 'KG' udm_list, round(dbms_random.value(40,2),2) prz_vend, round(dbms_random.value(8,2),2) margin, 'ART '||to_char(rownum*1000+rownum*124) description FROM DUAL d CONNECT BY ROWNUM <= 10 ) order by 1 ]'; dbms_output.put_line(v_vSQL); as_pdf3_v5.query2table(v_vSQL, r_fmt, as_pdf3_v5.tp_colors('000000',v_vHeadColor,'000000', '000000','ffffff','000000', '000000',v_vOddColor,'000000'), 15,15, 'mm',0,1 ); as_pdf3_v5.save_pdf(v_vOraDir, v_vFileName, TRUE); END;
Thank you! Got it to work and will attempt table queries to build a page.
RispondiEliminaThanks Valerio, the word wrap is exactly what I'm looking for.
RispondiEliminaThe tp_columns, however doesnt seem to change font for hFontName, I tried entering both Helvetica, Times-Roman with no change, any ideas ?
You can try the new release linked in this page,
Eliminahttp://valeriorossetti.blogspot.com/2014/07/aspdf3v5-new-features-versione-italiana.html
this bug are fixed and some new featurs are added.
Is there anyway to wrap text in headers?
RispondiEliminaNo there isn't. I'll try to implement it as soon as possible
RispondiEliminaThank you for the quick response. Can you also let me know if there is a way to adjust each row's height in a "query2table" to have a dynamic size. For example, I have noticed that if one cell has a really large number of characters then all the rows would have the same height of that cell. Isn't there a way to define that the height of the row would be the same as row's cell with the largest height?
EliminaIs there anyway to make the height of each row in a "query2table" to be calculated dynamically based on the row's cell with the highest height. For example, I have seen that when you run the query2table, all rows have the same height and that is the height of the cell with the largest height in the whole table. What I am searching for is for each row to have the same height but when a cell becomes larger because of the content it has to display, then only that row will become bigger. Not all of them.
EliminaHi Giannos, in response to question 15:43, there is a way.
EliminaYou can define the minimum height for each rows using a negative value for p_tRowHeight, but I found a bug. The height was never cleared. I have released version 5.3.07 that corrects this problem.
You con fund it in new post "AS_PDF3_V5 new features" (link at the top of this post)
I did not understand if you need the function (question 12:00) to automatically find the maximum height to be applied to all rows in the table.
I have just used v07 but it does not seem to do what I am seeking for. Maybe my description was not clear. Please see the image in the link(https://www.dropbox.com/s/2319l2rgyz03ktm/AS_PDF.png?dl=0),showing what the problem is. Thank you
EliminaI'm sorry, your description was clear, but thwere was a little bug in the code, upgrade to v08 should fix it.
EliminaI understand what you need, It should be easier than wordwrap on label
RispondiEliminaPls help me below
RispondiEliminabegin vr_test1('STANDARD'); end;
ORA-01403: no data found
ORA-06512: at "SYS.AS_PDF3_V5", line 4817
ORA-06512: at "SYS.AS_PDF3_V5", line 5217
ORA-06512: at "SYS.AS_PDF3_V5", line 5287
ORA-06512: at "SYS.VR_TEST1", line 345
ORA-06512: at line 1
Sorry for the bug, I fixed it in the package body at line 4792.
RispondiEliminaThe example was born with the first version and doesn't always work with the latest.
Download link was updated too.
Hi Valerio,
RispondiEliminaI need to add a line of text into the header and footer of a multiple-page PDF stored in database column. How can I do this?
Any help would be very appreciated.
HX
Hi H Xu,
EliminaI did not understand very well,
text header is stored in a database column.
The value is the same for the whole document, or change for each page?
I try to answer and then tell me if I missundertud
This is sample code for setting Header & Footer.
-- Define Header and Footer
v_vPageProc := q'[
begin
§.set_font('helvetica', 'B', 10 );
§.put_txt('mm', 5, 5, 'Valerio Rossetti');
§.put_txt('mm', 90, 5, 'Data: ');
§.set_font('helvetica', 'N', 10);
§.put_txt('mm', 115,5, ']'||to_char(sysdate,'dd/mm/yy')||q'[');
§.put_txt('mm', 175,5, 'Page #PAGE_NR# of #PAGE_COUNT#');
end;
]';
as_pdf3_v5.set_page_proc(v_vPageProc);
The procedure set_page_proc defines a piece of code that is executed at the end of the document, which add a bit of text on each page.
The special syntax is
§ which will be replaced with the name of the package
#PAGE_NR# variable with the page counter
#PAGE_COUNT# variable with total page count
, but other than that it is a common begin .. end block
you can replace static text with anything else.
If header are the same for each page, store it into variable, and use into pageproc:
v_vHeaderText varchar2(200);
Select HeaderColumn into v_vHeaderText
from HaderTable
Where ..... ;
v_vPageProc := replace(
q'[
begin
§.set_font('helvetica', 'B', 10 );
§.put_txt('mm', 5, 5, '##MY_HEAD##');
end;
]', '##MY_HEAD##', v_vHeaderText);
as_pdf3_v5.set_page_proc(v_vPageProc);
if header change for every page you must insert the select code inside pageproc
DECARE
v_vHeaderText varchar2(200);
BEGIN
Select HeaderColumn into v_vHeaderText
from HaderTable
Where ..... ;
§.put_txt('mm', 5, 5, v_vHeaderText);
END;
I hope that my suggestions will be helpful.
Pleased to to respond in the future
I'm sorry you had to wait 12 hours, but evaluates weekends and the time zone in Italy is 8:00 AM and I'm just woke up
Valerio
Hello;
RispondiEliminaI'm trying to use query2table (v3.5.10) but I'm facing an issue :
if I add tp_colors(color1, color2) for a query with only 2 columns this happens :
ORA-29253: Invalid count argument passed to procedure dbms_sql.define_array
if I just put NULL for the color part I have this
ORA-06531: Reference to uninitialized collection
Can you give me some help please ?
Regards
Doriane
Hi Doriane,
Eliminaas_pdf3_v5.tp_colors specifies 9 colors,
firts 3 colour are paper, ink and border of heading row
next 3 colour are paper, ink and border of even data row
last 3 colour are paper, ink and border of odd rows
If you don't wont odd/even highlight usa the same colous.
(some like this)
as_pdf3_v5.tp_colors('000000',v_vHeadColor,'000000',
'000000','ffffff','000000',
'000000',v_vOddColor,'000000')
Thanks
New version 3.5.11 solve your problem, remebre to use '' instead of null for p_colors parameter
EliminaHi Valerio Rossetti,
RispondiEliminaI have problem when I try to copy/paste your version of as_pdf3. In pl sql I don't see procedures or function on left side, but everything compiles without warnings and errors. I can use your packet without problem, but it is very hard without seeing on the left side.
And my next question is how to spread my table to the end of the page? I try with setting marrgins, changing t_y in some number... but without succes... For this I am using Anton's package-package body.
Thanks,
Milica
Hi Valerio,
RispondiEliminaThanks for posting your code it's really great...
I have two questions for you. When I compiling your code I don't have errors or warning, and I can call your procedures and functions from other procedure, and everything works great. But it does not show me structure of procedures/functions on the left side, and it's wery hard to me to read and walk trought your code.
Second question is about Anton's package body. I'm interested in posting table in pdf document from query2table. Everything is good but I don't know how to move my table to the bottom of page. Can you give me some tips? I know that solution is in y coordinate, but I'm not capable to get out of box :).
Thank you,
Milica
Thank you for appreciation.
EliminaIt's very strange, I'm using pl/SQL developer (V 11.0.5 by allroundAutomation), and using view spec & body I can view structure on left side (sceenshot here https://drive.google.com/open?id=0Bwc9IYMulx70cVZWNWdQRUIwZ0U).
I do not remember how to move down the table, I should review the code. Have you tried to set x,y coordinates and print a blank line ?
Give me a bit of time and I will be more specific.
Thank you for responding.
EliminaYes I try to set coordinates and move table from top, but when I'm moving table, the result is cutting bottom of table and move to next page. I also try to set margins, but without success.
Milica
Let's see if I well understand your question .
EliminaDo you want to insert a table aligned with the bottom of the sheet , in other words you'd like determine the height of the table to calculate the y coordinate to use?
Yes. I want to have a control of position of table (bottom, left, right...), and if I want to choose to spread a table to be capable to doing that (within the limits of paper format, of course).
RispondiEliminaThank you very much for responding,
Milica
The 3.5.11 version does not allow you to control the position of the table, but only to define the offset relative to the top and left margins .
EliminaI realized the .12 version, now in the debugging phase, in which I implemented the horizontal alignment, it was easy because I know in advance the table width.
The vertical alignment is more complicated because I don't know the height of the table until the end of the print process.
If I know table height, can try to set p_startY = (PageHeight - TopMargin -BottomMargin -TableHeight)
If I don't know the height of the table, I would need to perform printing process 2 times, the first time to determine the height of the table, then clean the print, set p_startY and repeat print.
But, what should I do when the table is printed on multiple pages ? In this case, each page can have a different height of the table.
I hope Valign is not needed in this case.
Valerio
Hi Valerio,
RispondiEliminaI have to say this is a great package that help to make Oracle more powerful and solve many problems for developers like me.
I have your package version of 3.5.12 and is also trying to use the query2table function. However, I am unable to print the table at the correct position after some header data. It always print at the top overlapping the header data. I wonder if I am missing something or doing something not right. I hope you can give me some advise.
This is how I call it:
as_pdf3_v5.query2table(v_vSQL,
r_d1_fmt,
'ffffff',
0, -- no header
6, -- row height
'mm',
20, -- p_startX
0,
1,
250 -- p_startY
);
Thank you. William.
Hi Valerio,
RispondiEliminaSorry for the previous question. I finally figured out. I set the offsetX and offsetY in the first column and now it is working fine.
Thank you. William
How can i show pdf in browser instead of saving ?
RispondiEliminaYou can use get_pdf function which returns BLOB data of PDF.
EliminaExample:
select 'application/pdf', as_pdf3_v5.get_pdf() from dual
Sorry, I don't know.
RispondiEliminaHi Valerio,
RispondiEliminaI have used this package for creating pdf document using SQL query. Query is returning 2 rows but in pdf it is displaying in table and there are 3 rows including empty row on top.
how to avoid the empty table row on top? do I need to comment any code?
Thanks in advance..
Hi Valerio,
RispondiEliminaI am facing a problem. When using query2table procedure to show query data in table form,
Empty table row is adding on top and 3 rows displayed whereas query returns only 2 rows.
Thanks.!
Hi Adhilakshmi,
EliminaWithout code I can only speculate, query2table presupposes a column header, do you have configured it ? (see exemple code at line 42).
If you don't want the column headings, please set hRowHeight = 0, it's the fourth parameter of query2table, immediately after the colors
I hope to be helpful, otherwise please send me your code.
Valerio
I was thinking back to your question, maybe you asking me how to get the clob PDF without saving it? You can do it insteda of
RispondiEliminaas_pdf3_v5.save_pdf(v_vOraDir, v_vFileName, TRUE);
use:
blobPDF blob;
blobPDF := as_pdf3_v5.get_pdf;
now blobPDF contain your pdf file without saving it !
Perhaps at this link our friend Tom gives us a cue to send the PDF stored into a blob to the browser
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::p11_question_id:232814159006
Hi,
RispondiEliminaI am trying to use your code to create a pdf file.
I have a dynamic sql and passing the query (v_query1) as follows:-
as_pdf3_v5.query2table( v_query1,
v_col_format,
as_pdf3_v5.tp_colors('000000',v_vHeadColor,'000000','000000','ffffff','000000','000000',v_vOddColor,'000000'),15,15, 'mm',0,1);
I am getting 'no data found' oracle error. When I am running the SQL in v_query1 in isolation then it is returning data.
Can you please help?
Thanks
Saty
Hi Saty,
EliminaI have never experienced this mistake, I can only make hypotheses,forgive me if I'm banal.
I guess you've tried the example at the beginning of this page and it worked.
The following code writes the number of rows returned by the dynamic query, if I understand using your query1 it works.
declare
v_rows number;
v_query1 varchar2(1000) := 'select * from dual';
begin
execute immediate 'Select count(*) from ('||v_query1||')' into v_rows;
DBMS_OUTPUT.PUT_LINE( to_char(v_rows));
end;
Can you run in debug mode to see the exact point where the error is generated?
Sorry but the information is very few and for me it is difficult to replicate the error on my system.
If you can, send me an example of your query and the chema of the tables at this email address:
Eliminablogcodesnippets-valerio_at_yahoo_dot_it (replace _at_ and _dot_ width correct chars)
Questo commento è stato eliminato da un amministratore del blog.
RispondiEliminaQuesto commento è stato eliminato da un amministratore del blog.
RispondiEliminaQuesto commento è stato eliminato da un amministratore del blog.
RispondiEliminahi.
RispondiEliminaim korean.
this package good...
but, have to use unicode (arial unicode)
how to make init_core_font arialuni.ttf
this method to slow (execute time : 60 seconds)
as_pdf3_v5.set_font( as_pdf3_v5.load_ttf_font( 'MY_FONTS', 'arialuni.ttf', 'CID'), 10 );
i'd appreciate it if you could tell me how to make "init_core_font <- arialuni.ttf".
Hi
RispondiEliminathe core of this package was written by Anton Sheffer.
The function load_ttf_font do this
1 Load ttf file into blob
2 Parse blob and load it font into a record of type tp_font named this_font
3 add this_font into table of g_fonts and return index position
I think that more time is used for parsing, my idea is:
Add a table to Db with same recordtype of tp_font.
Load ttf font and save this_font into table (only 1 time).
Add a function load_ttf_font_from_db that read this_font from db ad add to font table.
What do you think about it ?
If you like, you can send me the functions to save and read the font from db so I add it to the package.
Thank you.
EliminaIf so, please let me try again.
Thank you for responding to my inquiry.
my email : sonicbaba@hanmail.net
I have problems generating a loop for loop with query2table when executing query2table for the second time (vSQL, r_Fmt, as_pdf3_v5.tp_colors ('000000'), 15,5, 'mm'); I generate this error
RispondiEliminaORA-06502: PL / SQL: numeric or value error
ORA-06512: in "ARAS.AS_PDF3_V5", line 1643
ORA-06512: in "ARAS.AS_PDF3_V5", line 1664
ORA-06512: in "ARAS.CREATE_PDF", line 648
ORA-06512: online 13
Hi, please can you past me code line 1643 to 1664 ?
Eliminaclear...
Eliminafunction set_font
( p_family varchar2
, p_style varchar2 := 'N'
, p_fontsize_pt number := null
, p_output_to_doc boolean := true
)
return pls_integer
is
t_family varchar2(100);
t_style varchar2(100);
begin
if p_family is null and g_current_font is null
then
return null;
end if;
if p_family is null and p_style is null and p_fontsize_pt is null
then
return null;
end if;
t_family := coalesce( lower( p_family )
, g_fonts( g_current_font ).family
);
t_style := upper( p_style );
t_style := case t_style
when 'NORMAL' then 'N'
when 'REGULAR' then 'N'
when 'BOLD' then 'B'
when 'ITALIC' then 'I'
when 'OBLIQUE' then 'I'
else t_style
end;
t_style := coalesce( t_style
, case when g_current_font is null then 'N' else g_fonts( g_current_font ).style end
);
-- ******************************************LINE 1643***********************
for i in g_fonts.first .. g_fonts.last
loop
if ( g_fonts( i ).family = t_family
and g_fonts( i ).style = t_style
)
then
return set_font( g_fonts( i ).fontname, p_fontsize_pt, p_output_to_doc );
end if;
end loop;
return null;
end;
--
procedure set_font
( p_family varchar2
, p_style varchar2 := 'N'
, p_fontsize_pt number := null
, p_output_to_doc boolean := true
)
is
t_dummy pls_integer;
begin
t_dummy := set_font( p_family, p_style, p_fontsize_pt, p_output_to_doc );
end;
-- Change only font style
Thanks, I can try to debug it on Monday morning at work because at home I have not oracle database installed
EliminaOk Thanks, I'm going to send you the procedure so you can see what I'm trying to do
Elimina/***************************************************************************************/
/**********************The sql statement yields a result of two data*********************/
v_vSQLs := v_vSQLs||' SELECT..... '||sENT;
OPEN ccursor FOR v_vSQLs;
LOOP
FETCH ccursor INTO vLinea;
EXIT WHEN ccursor%NOTFOUND;
v_vSQL := '';
i:=1; -- (riga di rottura
r_Fmt.extend(3);
r_Fmt(i).colWidth:=17;
r_Fmt(i).colLabel:='No. Factura';
r_Fmt(i).hFontStyle:='B';
r_Fmt(i).hFontSize:=8;
r_Fmt(i).hAlignVert:='T';
r_Fmt(i).tAlignment:='C';
r_Fmt(i).tCHeight := 5;
r_Fmt(i).hCHeight := 7;
r_Fmt(i).cellRow := 1;
i:=i+1; --2
r_Fmt(i).colWidth:=26;
r_Fmt(i).colLabel:='Núm. Contenedor';
r_Fmt(i).hFontStyle:='B';
r_Fmt(i).hFontSize:=8;
r_Fmt(i).hAlignVert:='T';
r_Fmt(i).tAlignment:='C';
i:=i+1; --3
r_Fmt(i).colWidth:=29;
r_Fmt(i).colLabel:='Número BL';
r_Fmt(i).hFontStyle:='B';
r_Fmt(i).hFontSize:=8;
r_Fmt(i).hAlignment:='C';
r_Fmt(i).hAlignVert:='T';
r_Fmt(i).tAlignment:='C';
v_vSQL := v_vSQL||'SELECT CAMPO1, CAMPO2, CAMPO3..... '||sENT;
as_pdf3_v5.query2table(v_vSQL, r_Fmt, as_pdf3_v5.tp_colors('000000'), 15,5, 'mm');
as_pdf3_v5.save_pdf(v_vOraDir, v_vFileName, TRUE);
END LOOP;
Good idea.
EliminaIf I understand, you would like to produce a pdf file for each record in the v_vSQLs query.
Some questions,
r_Fmt is defined into the loop, but his values seems to be constants with no reference to vLinea. You can try to move it out of the loop.
The problem might be r_Fmt.extend (3) which adds 3 columns to each cycle, In this case in the second cycle, query2table finds a numbers of format columns different than the ones in the query.
When you reference vLinea ?
I hope this is a solution, please let me know if you can solve it, I'm curious
Ok ... Thanks for your collaboration,
EliminaI will answer your questions
1) r_Fmt already pulling out of the loop and indeed now if I paint the detail, the problem that comes with this is that I need to be dynamic example values.
I: = 1;
IF vLinea = 'SHIP' THEN
R_fmt.extend (5);
R_fmt (i) .colWidth: = 38;
I: = i + 1; --5
R_fmt (i) .colWidth: = 38;
I: = i + 1; - 6
R_fmt (i) .colWidth: = 38;
I: = i + 1; --7
R_fmt (i) .colWidth: = 38;
I: = i + 1; - 10
R_fmt (i) .colWidth: = 38;
ELSE
IF vLinea = 'KN' THEN
R_fmt.extend (10);
R_fmt (i) .colWidth: = 17;
I: = i + 1; --2
R_fmt (i) .colWidth: = 26;
I: = i + 1; --3
R_fmt (i) .colWidth: = 29;
I: = i + 1; --4
R_fmt (i) .colWidth: = 16;
I: = i + 1; --5
R_fmt (i) .colWidth: = 12;
I: = i + 1; - 6
R_fmt (i) .colWidth: = 21;
I: = i + 1; --7
R_fmt (i) .colWidth: = 16;
I: = i + 1; --8
R_fmt (i) .colWidth: = 18;
I: = i + 1; - 9
R_fmt (i) .colWidth: = 16;
I: = i + 1; - 10
R_fmt (i) .colWidth: = 19;
ELSE
R_Fmt.extend (9);
R_Fmt (i) .colWidth: = 20;
I: = i + 1; --2
IF vLinea = 'GEAR' THEN
R_Fmt (i) .colWidth: = 34;
ELSE
R_Fmt (i) .colWidth: = 29;
END IF;
I: = i + 1; --3
R_Fmt (i) .colWidth: = 32;
I: = i + 1; --4
R_Fmt (i) .colWidth: = 23;
I: = i + 1; --5
R_Fmt (i) .colWidth: = 12;
I: = i + 1; - 6
R_Fmt (i) .colWidth: = 21;
IF vLinea = 'GEAR' THEN
I: = i + 1; --7
R_Fmt (i) .colWidth: = 15;
I: = i + 1; --8
R_Fmt (i) .colWidth: = 14;
ELSE
I: = i + 1; --7
R_Fmt (i) .colWidth: = 16;
I: = i + 1; --8
R_Fmt (i) .colWidth: = 18;
END IF;
I: = i + 1; - 9
R_Fmt (i) .colWidth: = 19;
END IF;
END IF;
Where vLinea biene of an SQL statement which can bring me one or several records.
With your answer I could already paint the SQL statement where it brings all the detail, now I need that for each vLinea also paint the header
Well,
RispondiEliminanumber of columns depends from vLinea, you must put R_fmt definition into loop.
Your code at point 1) work fine but we must clean R_Fmt at beginning of each loop
I := 1;
-- This Statment remove all elements from R_fmt
if R_Fmt.count>0 Then
R_Fmt.trim(R_Fmt.count)
end if;
--
IF vLinea = 'SHIP' THEN
..
Questo commento è stato eliminato dall'autore.
EliminaThank you very much for your help.
EliminaSorry for the last thing you could tell me how I can know the last position of p_y, thanks.
See below I understand your question in spanush
EliminaYou can use function get(7). Funtion get accept any constant c_get
RispondiElimina7 for current y, 6 for current x and so on
Sorry I tried to do it but I have not succeeded, if you could help me
EliminaI'll show you what I'm trying to do, after painting this information
As_pdf3_v5.query2table (v_vSQLc, r_Fmtc, as_pdf3_v5.tp_colors ('000000', 'ffffff', '000000', '000000', 'A4A4A4', '000000', '000000'));
I want to know the position p_y to be able to start the footer
As_pdf3_v5.set_font ('helvetica', 'B', 8);
As_pdf3_v5.write ('* Please send the payment support to these mail *', p_x => 35, p_y => ?);
If you write at current y position simply
EliminaAs_pdf3_v5.write ('* Please send the payment support to these mail *', p_x => 35);
When p_y is null or missig procedure write use current y value, the same for p_x.
Good day,
EliminaOK ... Actually not placing the position And the pint underneath, this works for me perfect for the write () function, but for horizontal_line () no, for this function I must pass the parameter Y and I try to make the Page is enclosed in a box.
try this (I'm at home and can't test it)
RispondiEliminaas_pdf3_v5.horizontal_line( p_x := 1, p_y :=as_pdf3_v5.get( as_pdf3_v5.C_GET_Y ) , p_width := 100);
replace p_x, p_width with correct values in PT.
Thank you for what you provided, it was very helpful.
EliminaI'll bother you with one last thing as I can control the creation of a new sheet, that is if the information I paint in my pdf is very at the end of the sheet 1 I want my footer to go to the next page It does but it is divided, a piece in sheet 1 and the rest in sheet 2.
Apologize me if my answer is silly.
EliminaUse new_page procedure to create new sheet.
function chkNewPage(y in number, t_line_height in number) return number is
t_y number;
begin
-- Update t_y and check in new page are necessary
t_y := y - t_line_height;
if t_y < g_settings.margin_bottom then
new_page;
t_y := g_settings.page_height - g_settings.margin_top - t_line_height;
end if;
return(t_y);
end;
This function, (you can find itat beginning of Write procedure), is an example of how to test whether text goes beyond the end of the page.
Instead of t_line_height, use eight of your footer = (LineHeight*NumeberOfRows).
This is an example on how to calculate LineHeight
t_line_height := nvl( conv2uu(p_line_height,p_um ), g_fonts( g_current_font ).fontsize );
Buongiorno Valerio,
RispondiEliminacomplimenti per il suo eccellente lavoro,
volevo chiederle come poter inserire internamente un nuovo font, come già presenti altri tipi di font, non posso caricare esternamente un font, ma non capisco come sia codificato il font interno, se esiste qualche generatore online per poter convertire un font nelle stringhe interne per la definizione di un nuovo font.
Grazie
Salvatore
Buonasera Salvatore,
Eliminagrazie per i complimenti, ma buona parte del merito è di Anton Sheffer.
Se ho capito bene si riferisce alla procedura init_core_fonts, tale procedura è stata scritta da Anton e serve per definire i font incorporati in AdobeReader. Gli esempi mostrano come caricare un font da un file, tuttavia esistono più definizioni della procedura load_ttf_font, tra queste alcune accettano un blob. Ora non le resta che caricare in una variabile blob il contenuto del file con il font che vuole usare. Prendendo spunto dalla tecnica usata da Anton si potrebbe:
leggere il file in blocchi (esempio 2Kbyte) codificare in base64 (utile per scongiurare la presenza di caratteri speciali o delimitatori), il testo ottenuto va racchiuso tra ' e associato a una variabile varchar2.
Nel package si può aggiungere una procedura decodifica la stringa in base64 e la accoda alla variabile blob (usando la procedura dbms_lob.append ).
Valerio
WHO COULD I CREATE A PDF DOCUMENT BUT IN A PDF VERSION MORE THAN 1.4?? BECAUSE THIS PACKAGE SEEMS TO CREATE IT IN 1.3 VERSION....THANK YOU FOR YOUR HELP.
RispondiEliminaI do not know, I have only added some features to the original package by Anton Sheffer
RispondiEliminahttps://technology.amis.nl/2012/04/11/generating-a-pdf-document-with-some-plsql-as_pdf_mini-as_pdf3/
Hi, i want your help
RispondiEliminamy PDF is up to five pages, I would like to leave it twice, could you tell me how I can do this.
Hello, I'm not sure I understand the question, do you want the number of pages to always be even? Or do you want to use the pdf document twice?
EliminaIn the first case you can modify procedure finish_pdf.
procedure finish_pdf
is
t_xref number;
t_info number(10);
t_catalogue number(10);
begin
-- Add une page if document is empty
if g_pages.count = 0 then
new_page;
end if;
-- Add one page if number of pages is odd
if mod(g_pages.count, 2) = 1 then
new_page;
end if;
...
end;
In the second case it is quite easy, in the example the last procedure
as_pdf3_v5.save_pdf(v_vOraDir, v_vFileName, TRUE);
save document to file and release CLOB variable where PDF is stored.
Changing last parameter to FALSE, you preserve CLOB variable
To get the CLOB variable after saving you will have to modify the function get_pdf
in spec:
function get_pdf(bFinish in boolean := TRUE) return BLOB;
in body:
function get_pdf(bFinish in boolean := TRUE) return BLOB is
begin
if bFinish then
finish_pdf;
end if;
return g_pdf_doc;
end;
calling get_pdf(FALSE) you can retrieve CLOB variable containing PDF document and use it many times you want.
Thanks, what I want is that you do not have a limit on the number of pages per document, apparently it has a limit of five pages
EliminaThanks, the problem I have is that the pdf document is generated until page five and I require that it does not have a page limit
EliminaQuesto commento è stato eliminato dall'autore.
Eliminathere is no limitation in the number of pages, I have in production reports of over than 100 pages.
EliminaIf you try example at top of this page and change the row
FROM DUAL d CONNECT BY ROWNUM <= 10
from 10 to 100 or more you obtain a pdf with 7 or more page.
Ok, isn't a beauty example, the scope is to demostrate that there isn't a limitation.
Does your the PDF production stop with some errorr code after page five ?
For my experience often the problem is data to write. If you can send me an example of your pdf, I can try to debug it.
Hi, my name is Toni and I’m a Spanish programmer.
RispondiEliminaI’m modifying the code to adapt it to our needs in Spain, but I can’t get accentuated vowels (á,é,í,ó,ú, Á,É,Ó,Ú).
You could tell me that I have to modify in the code as_pdf3_v5 to get accented vowels in the final pdf.
I usually use truetype fonts that load with Loadttf embedded in the document.
How can I get a PDF/A document with the package AS_PDF3_V5?
RispondiEliminaHi Tony, I'm sorry but I don't know how to help you.
RispondiEliminaThe package was written by Anton Sheffer, especially the procedures that write the PDF. I've only added some features. I believe that to adapt the package to the PDF / A format it is necessary to compare the documentation of the two formats and adjust all the file writing procedures.
As for the accented vowels, I usually use them in my documents in Italian, but I usually don't use TTF. Give me a couple of days to do a test with TTF . See you soon
Hi Valerio,
RispondiEliminaThanks for sharing your work. I tried to run an example your provided (https://drive.google.com/file/d/0Bwc9IYMulx70X3FjVXZNS0h0S3M/edit) but it does not work as expected. the table in PDF file is corrupted. Take a look https://ibb.co/NCXg1Rn
Any ideas why?
Regards,
Greg
with that example I wanted to show too many things at once, but result isn't very good.
Eliminawhat do you expect to see? a classic table?
The trick is in the configuration of the columns.
Almost Worked Everything mentioned. Excellent work... Beautiful Barcodes ...All Good
RispondiElimina# Bug: When column width is 0 and the value is numeric, the value still gets printed.
However if the column type is text, the column value gets hidden.
I use column width=0 where I wish to hide the columns...
Thanks, Please post an update !!
When query2table() is called with p_bulk_size=0 for an unlimited number of lines, and the result set happens to be empty, then dbms_sql.define_array() is called with cnt=0, which makes it throw an ORA-29253. One way to prevent this is to insert a case for bulk_size=0:
RispondiEliminacase
when p_bulk_size = 0 then
null;
when t_desc_tab( c ).col_type member of t_numerics then
dbms_sql.define_array( p_c, c, n_tab, p_bulk_size, 1 );
when t_desc_tab( c ).col_type member of t_dates then
dbms_sql.define_array( p_c, c, d_tab, p_bulk_size, 1 );
when t_desc_tab( c ).col_type member of t_chars then
dbms_sql.define_array( p_c, c, v_tab, p_bulk_size, 1 );
when t_desc_tab( c ).col_type member of t_blobs then
dbms_sql.define_array( p_c, c, b_tab, p_bulk_size, 1 );
else
null;
end case;
That seems to successfully suppress the table when no data is found.
Many thanks.
EliminaHi valerio,
RispondiEliminaI know it has been awhile since receiving questions. Hopefully I can still get some answers.
1. Can I do any type of text alignment using write in header ? If not using write any other possibilities for text boxes with text wrapping in header without me having to compute manually?
Thanks,
Tom
Hi Tom
Eliminain the above example, line 45 specifies the horizontal alignment for the column heading.
unfortunately I never had the need to use text wrapping for the column header. The implementation is not trivial, it is necessary, at the very least, to transform the headers from string to string array and replace the procedure that calculates the height of the header row
Valerio,
RispondiEliminaThanks for the response. I will work around. I am getting into details of working with query2table and when I hide the headers I am getting a space above the table I cannot seem to get rid of. The headers don't show but the space remains. I am trying to stack tables with no space in between. Any suggestion appreciated. Also any text underlining capability or do I have to implement manually. Great package !!!
Thanks,
Tom
Also in my previous question I should have put text alignment in "PAGE HEADER" ? Can you only use put in there and not write ?
RispondiEliminaI'm sorry, any experience with Oracle 19c. You can Try tro tpocontact original author Anton Sheffer
RispondiEliminaHi Can you share the code encrypted Password in PDF.
RispondiEliminaThanks in Advance
I’m sorry I jave no code for encrypt pdf
EliminaHI,
RispondiEliminaI've generated PDF Successfully, Now i need PDF encrypted with Password. Can you share me the Code for the same.
Thanks In advance
Hi valerio, I've generated PDF Successfully, use Barcodes but when scanning it, it does not show the correct information
RispondiEliminaHi Mairena,
RispondiEliminahow did you generate the barcode?
Hi Valerio,
RispondiEliminaI am in the following circumstance.
The pdf file already exists in a table on a BLOB column ...and inside the pdf file I have the strings #NAME# and #TABLE#.
Using AS_PDF3_V5 package, can I replace in the pdf file the two strings with data taken from the database?
1) #NAME# with customer name (e.g replacement of #PAGE_NR# with the current page number).
2) #TABLE# with a query result (e.g using QUERY2TABLE procedure).
Thanks for any help or advice,
Ciprian
Hi Valerio, having generated successfully some PDF with your PL/SQL package, I find it however quite tedious to manually, by code, create the PDF report layout.
RispondiEliminaI've come up with a different approach for generating PDF reports from an ORACLE SQL query which ease significantly the PDF layout creation.
It involves a Powershell Script, a Reportviewer RDLC component and the Oracle Managed Client dll.
The big advantage is that the PDF report creation, can be done very quickly from Visual Studio designer, graphically.
The powershell script pull the data from the DB and send it to the report (classic .Net code ported to Powershell).
You can then add the powershell script to a windows task scheduler for instance and voilà, you can send by mail PDF, XL or Word reports very easily.
I'll be glad, if you're interested, to send you a complete test case.
Fill free...
Olivier
Great job Oliver.
RispondiEliminai changed job and i no longer follow pdf production in oracle, but your work may be useful to others. ASPDF is tedious, but in my case I was forced to produce pdf from automatic procedures scheduled in the oracle environment, so no windows.
Not a great solution but I added a double replace in txt2raw that repaces () with [] at the top into a new text variable and then use that and it's working with just that change. I haven't had time to go deeper into why yet and am calling it a day. If I need to use () or discover other characters, etc I'll update again.
RispondiEliminaI had the same problem. In package as_pdf3, I replaced
RispondiEliminafunction pdf_string( p_txt in blob )
return blob
is
t_rv blob;
with
function pdf_string( p_txt in raw )
return raw
is
t_rv raw(32767);
... and it worked like before!
Cheers, Rob
Hi,
RispondiEliminaI need to put a hyperlink on Image in the PDF document. So that by clicking on it to open the web page. Is there a way to do this with as_pdf3?
Sorry, I don't know how hyperlinks are implemented in pdf documents. This package is many years old and I have only added some features to Anton Sheffer's original pkg
RispondiEliminaI had an issue with ( ) brackets, I replaced them with [ ] and it fixed the package from hanging, I am not sure why.
RispondiEliminaThanks for wonderful job. Table Column grouping is possible. i.e subcolumn
RispondiEliminaThanks, most of the credit goes to anton sheffer. the requested functionality is not provided and I can't help you because I don't work on oracle structures anymore. Sorry
RispondiElimina