on 05-25-2016 9:58 AM
Hello Gurus,
I have few questions about SAP PDF Interactive forms. I am not doing interactive form, but simple printout, but I want some "layout changes" before I send it to printer/show the form to the user.
For example I am doing material movements and I want to make per page sums per unit. E.g.
I have 5 PCE, 10 KG, 20 L and I want to make subtotals/totals per unit, but I am unable to do it dynamically (or AM I?).
It is not a problem to get sums into a JS object in form e.g.
{ PCE : { Column1: Value, Column2: Value }, etc.}
The problem I see is that I am unable to do "dynamic page breaks" without conditional page break, but when I do conditional page break I need to find number of lines per page before the form start by counting and specifying how many lines there are per page, in ABAP (or is there any other way?) and then do conditional break on per page basis (working even though I don't find it elegant).
The other problem is, when I use conditional breaks I am unable to "duplicate" the subtotal line. When I try to access the instanceManager, it tells me, that it is null. So to do something like this.instanceManager.addInstance(1) is not usable (I am not telling that in official help I should use Layout:Ready function to fire up my own script to change layout, but on note I see, that I should not modify the layout DoH)
LiveCycle ES2 * Adobe LiveCycle Designer ES2
I hope I had explained myself clearly, although I had tried to describe what I have been through. The main question is. Am I able to do dynamic layout changes with script during AdobeForm generation? Or is there any way to get the dynamic per page subtotals to work, preferably with scripts, not counting in ABAP?
Thank you,
Regards,
Petr Sourek
Hello,
so I get it is impossible for simple PDF static form to get "dynamic" subtotals using JS so a little workaround, which I am not proud of, but well it works...
So if anyone needs it, you can:
- Draw form, in the table create header / data item (no footer is needed, we will redesign the data item row for subtotal),
- Count number of lines on 1st page (including totals) and on other pages, if signatures should be with the last data item on the page, count lines until signatures break on first and other pages
- Extend data structure of the table in DDIC and add field TOTALFIELD type char1,
- Create class, or FM, or whatever which will "create" table with (sub)totals for drawint the table into form, don't worry it is completely dynamic, so stick in the table and it will sum all the numeric fields (taken from domains)
Add constant into the class:
cTotalField type string value 'TOTALFIELD' , "#EC NOTEXT
Static method - definition (not in new manner, compatible with 7.31 ABAP), parameter description using abapdocu:
"! Method for preparing the table for printing (all total calculations made in abap), all you need to know is number of lines per page and
"! then implement javascript which will create the table for user in initialization event of table row
"!
"! @parameter nFirstPageLines | Number of lines on 1st page (mostly different, because there is header too), when omitted the nOtherPageLines is taken into account
"! @parameter nOtherPageLines | Number of lines on other pages (not 1st one)
"! @parameter nFirstSignLines | Number of lines on 1st page, when we have to make manual break (for signatures to be on the same page as at least one item)
"! @parameter nOtherSignLines | Number of lines on other pages (not 1st one), when we have to make manual break (for signatures to be on the same page as at leas one item)
"! @parameter sUnitField | Field with unit, according to which the sums are going to be dynamic
"! @parameter sAdditionalFields | Additional fields which are going to take value, eg. we are summing by unit field, but we want in total to show also the unit description,
"! but when we omit it, it will be shown empty
"! @parameter tTable | Table to alter (any standard table should do) the only prerequisity is, that the structure has TOTALFIELD type char1. It will sum
"! all numeric fields taken from their domains and to the TOTALFIELD it will fill these values:
"!
"! <ul>
"!<li><em>B</em> - After this line, we need to break, because the signatures are not going to be on the same page,</li>
"!<li><em>S</em> - This line is subtotal, so we can in JS make different layout of the line,</li>
"!<li><em>T</em> - This line is total, so we can in JS make different layout of the line,</li>
"!</ul>
prepareTableWithSums
importing
value(nFirstPageLines) type i optional
nOtherPageLines type i
value(nFirstSignLines) type i optional
nOtherSignLines type i optional
sUnitField type any
sAdditionalFields type string
changing
tTable type standard table
Static method - implementation (not in new manner, compatible with 7.31 ABAP):
method prepareTableWithSums .
"-- Declarations
"-- Trying new simpler syntax, since there should not be used the global vars, so I stripped G|L since they are useless
"-- Then simple:
"-- o - object,
"-- r - reference,
"-- b - bool,
"-- n - number,
"-- s - string,
"-- t - internal table (it is a little diferrent so I am not using a as array)
"-- st - structure
data:
oTable type ref to cl_abap_tableDescr ,
oStruc type ref to cl_abap_structDescr ,
rDummyTab type ref to data ,
rDummySum type ref to data ,
bFirstUsed type boolean ,
bBreak type boolean ,
nI type i ,
nNumOfLines type i ,
nProcLines type i ,
sUnit type mseh6 ,
sWhereField type string ,
sWhereCond type string ,
tFields type cl_abap_structDescr=>component_table ,
tAddFields type standard table of string ,
tUnits type standard table of mseh6 ,
stUnit like line of tUnits
.
"-- Field symbols
field-symbols:
type standard table ,
type standard table ,
like line of tAddFields ,
like line of tFields ,
type any ,
type any ,
type any ,
type any ,
type any ,
type any
.
break-point id zCA_form_main .
"-- When 1st page lines not set, use the same value as for other pages
if nFirstPageLines is NOT supplied .
nFirstPageLines = nOtherPageLines .
endif .
if nOtherSignLines is supplied and nFirstSignLines is NOT supplied .
nFirstSignLines = nOtherSignLines .
endif .
"-- Get table description, structure description and fields of table structure
oTable ?= cl_abap_tableDescr=>describe_by_data( tTable ) .
oStruc ?= oTable->get_table_line_type( ) .
tFields = oStruc->get_components( ) .
"-- Get additional fields
split sAdditionalFields
at ';'
into table tAddFields
in character mode
.
"-- Strip non numeric value from components
loop at tFields
assigning .
"-- Check if field should be at output
read table tAddfields
transporting no fields
with key
table_line = -name
.
case sy-subrc .
when 0 .
continue .
endcase .
"-- Delete non numeric fields
if -type->type_kind NE cl_abap_typeDescr=>typekind_decfloat and
-type->type_kind NE cl_abap_typeDescr=>typekind_decfloat16 and
-type->type_kind NE cl_abap_typeDescr=>typekind_decfloat34 and
-type->type_kind NE cl_abap_typeDescr=>typekind_float and
-type->type_kind NE cl_abap_typeDescr=>typekind_int and
-type->type_kind NE cl_abap_typeDescr=>typekind_int1 and
-type->type_kind NE cl_abap_typeDescr=>typekind_int2 and
-type->type_kind NE cl_abap_typeDescr=>typekind_num and
-type->type_kind NE cl_abap_typeDescr=>typekind_numeric and
-type->type_kind NE cl_abap_typeDescr=>typekind_packed
.
delete tFields .
endif .
endloop .
"-- Create dynamic return table and sum table which will be summed
create data rDummyTab type handle oTable .
create data rDummySum type handle oTable .
"-- Get their references
assign rDummyTab->* to .
assign rDummySum->* to .
check is assigned and is assigned .
"-- Init variables
nI = 0 .
nProcLines = 0 .
nNumOfLines = lines( tTable ) .
bFirstUsed = abap_false .
bBreak = abap_false .
sWhereField = sUnitField .
break-point id zCA_form_main .
"-- 1st page break
"-- Do it only once at last page and only if signature lines are passed in
if nFirstSignLines is supplied and bBreak eq abap_false and ( lines( tTable ) < nFirstPageLines ) .
"-- Get number of units on last page
free tUnits .
loop at tTable
assigning .
free stUnit .
if is assigned . unassign . endif .
assign component sUnitField
of structure to .
check is assigned .
stUnit = .
collect stUnit into tUnits .
endloop .
if bBreak = abap_false and ( lines( tTable ) + 2 * lines( tUnits ) > nFirstSignLines ) .
bBreak = abap_true .
endif .
endif .
"-- Do the math, by looping change table and append reference table
loop at tTable
assigning .
"-- Get sumIf field
if is assigned . unassign . endif .
assign component sWhereField
of structure to .
check is assigned .
"-- Get line in sum table with that field value
if is assigned . unassign . endif .
read table assigning with key
(sWhereField) = .
if is NOT assigned . "-- Not found, create
append initial line to assigning .
"-- Add flag
if is assigned . unassign . endif .
assign component cTotalField
of structure to .
if is assigned .
= 'S' .
unassign .
endif .
"-- Add sumif field value
assign component sWhereField
of structure to .
if is assigned .
= .
unassign .
endif .
endif .
"-- Now do the math, count numeric fields into sum table
loop at tFields
assigning .
"-- Get values
if is assigned . unassign . endif .
if is assigned . unassign . endif .
assign component -name of structure to .
assign component -name of structure to .
check is assigned and is assigned .
"-- Sum
read table tAddFields
transporting no fields
with key
table_line = -name
.
case sy-subrc .
when 0 .
= .
when others .
= + .
endcase .
endloop .
"-- Append normal table
append to .
"-- Increase iterator, for page/breaks
nI = nI + 1 .
nProcLines = nProcLines + 1 .
"-- 1st or other pages, count if we are at the correct number of lines per page
case bFirstUsed .
when abap_true .
"-- we need to subtract the subtotal lines
if nI = nOtherPageLines - lines( ) or ( nNumOfLines - nProcLines = 1 and bBreak eq abap_true )
.
case bBreak .
when abap_true .
"-- Get last line and assign break pattern
nI = lines( ) .
if is assigned . unassign . endif .
read table assigning index nI
.
if is assigned .
if is assigned . unassign . endif .
assign component cTotalField
of structure to .
if is assigned .
= 'B' .
unassign .
endif .
unassign .
endif .
endcase .
nI = 0 .
append lines of to .
free .
"-- Do it only once at last page and only if signature lines are passed in
if nOtherSignLines is supplied and bBreak eq abap_false and ( nNumOfLines - nProcLines < nOtherPageLines ) .
"-- Get number of units on last page
free tUnits .
loop at tTable
assigning from nProcLines to nNumOfLines
.
free stUnit .
if is assigned . unassign . endif .
assign component sUnitField
of structure to .
check is assigned .
stUnit = .
collect stUnit into tUnits .
endloop .
if bBreak = abap_false and ( nNumOfLines - nProcLines + 2 * lines( tUnits ) > nOtherSignLines ) .
bBreak = abap_true .
endif .
endif .
endif .
when abap_false .
"-- we need to subtract the subtotal lines
if nI = nFirstPageLines - lines( ) or ( nNumOfLines - nProcLines = 1 and bBreak eq abap_true ) .
bFirstUsed = abap_true .
case bBreak .
when abap_true .
"-- Get last line and assign break pattern
nI = lines( ) .
if is assigned . unassign . endif .
read table assigning index nI
.
if is assigned .
if is assigned . unassign . endif .
assign component cTotalField
of structure to .
if is assigned .
= 'B' .
unassign .
endif .
unassign .
endif .
endcase .
nI = 0 .
append lines of to .
free .
"-- Do it only once at last page and only if signature lines are passed in
if nOtherSignLines is supplied and ( nNumOfLines - nProcLines < nOtherPageLines ) .
"-- Get number of units on last page
free tUnits .
loop at tTable
assigning from nProcLines to nNumOfLines
.
free stUnit .
if is assigned . unassign . endif .
assign component sUnitField
of structure to .
check is assigned .
stUnit = .
collect stUnit into tUnits .
endloop .
if bBreak = abap_false and ( nNumOfLines - nProcLines + 2 * lines( tUnits ) > nOtherSignLines ) .
bBreak = abap_true .
endif .
endif .
endif .
endcase .
endloop .
"-- Looped entire table, and append last page subtotals
if lines( ) > 0 .
append lines of to .
free .
endif .
"-- Prepare total lines
sWhereCond = |{ cTotalField } = 'S'| .
free .
loop at assigning where
(sWhereCond)
.
"-- Get sumIf field
if is assigned . unassign . endif .
assign component sWhereField
of structure to .
check is assigned .
"-- Get line in sum table with that field value
if is assigned . unassign . endif .
read table assigning with key
(sWhereField) = .
if is NOT assigned . "-- Not found, create
append initial line to assigning .
"-- Add flag
if is assigned . unassign . endif .
assign component cTotalField
of structure to .
if is assigned .
= 'T' .
unassign .
endif .
"-- Add sumif field value
assign component sWhereField
of structure to .
if is assigned .
= .
unassign .
endif .
endif .
"-- Now do the math, count numeric fields into sum table
loop at tFields
assigning .
"-- Get values
if is assigned . unassign . endif .
if is assigned . unassign . endif .
assign component -name of structure to .
assign component -name of structure to .
check is assigned and is assigned .
"-- Sum
read table tAddFields
transporting no fields
with key
table_line = -name
.
case sy-subrc .
when 0 .
= .
when others .
= + .
endcase .
endloop .
endloop .
append lines of to .
free .
unassign .
free tTable .
tTable = .
free .
unassign .
endmethod .
- To the form interface add the table creation,
"-- Create table with sums for chapter1
zCAClPDFForm=>prepareTableWithSums(
exporting
nFirstPageLines = 25
nOtherPageLines = 31
nFirstSignLines = 12
nOtherSignLines = 25
sUnitField = 'VRKME'
sAdditionalFields = 'MSEHT'
changing
tTable = tItems
) .
- Add three variables to the form (form properties):
bBreak value false
bPreviousSubtotal value false
nPageBreakAt value 0
- at the data item, define new conditional break and in the code select javascript, client and server, insert this line
this.index === parseInt(nPageBreakAt.value) && parseInt(nPageBreakAt.value) > 0
- At the data item, go to script and select initialization event (here we don't know page number, but we can redraw the item according to the TOTALFIELD value) so insert this javascript, client and server:
data.Layout1.table.dataRow::initialize - (JavaScript, both)
// How to make dynamic totals SAP and Adobe ways, Oh Steve you should have made Adobe go Bancrupt...
// Get the value from totalField
try {
function convertToTotalLine(oLine) {
// This will simply create total line, so we merge columns, change alignment, etc. alter to your needs
oLine.C1.colSpan = "3";
oLine.C2.presence = "hidden";
oLine.C3.presence = "hidden";
oLine.C1.para.hAlign = "right";
oLine.C1.font.weight = "bold";
oLine.C1.border.presence = "hidden";
oLine.C1.value.text.maxChars = "0";
}
// Process only when NOT null
if ((xfa.resolveNode('xfa.record.TITEM.DATA[' + this.index.toString() + '].TOTALFIELD') !== null) && (xfa.resolveNode('xfa.record.TITEM.DATA[' + this.index.toString() + '].TOTALFIELD').value !== null)) {
switch(xfa.resolveNode('xfa.record.TITEM.DATA[' + this.index.toString() + '].TOTALFIELD').value.toString()) {
case 'S':
convertToTotalLine(this);
this.C1.rawValue = 'Per page sums';
if (bBreak.value === 'true') {
bPreviousSubtotal.value = 'true';
}
break;
case 'T':
convertToTotalLine(this);
this.C1.rawValue = 'Total for document';
break;
case 'B':
bBreak.value = 'true';
break;
}
} else {
if ((bBreak.value === 'true') && (bPreviousSubtotal.value = 'true')) {
nPageBreakAt.value = this.index.toString();
bBreak.value = 'false';
bPreviousSubtotal.value = 'false';
}
}
} catch(e) {
xfa.host.messageBox(e.message);
}
- And last but not least, we need to make the conditional breaks to work, so at data item create formcalc script for event ready::form and insert this script:
data.Layout1.table.dataRow::ready:form - (FormCalc, both)
// This will make conditional break to work
$.#breakBefore.target = "contentArea";
// Instead of Header write the table header name (it can also be a subformset when you are doing e.g. 3 lines of table header
// wrap them into subform set and insert its name here
$.#breakBefore.leader = "Header";
And that's it, I am in the middle of tests at the moment, there might be a little calculation problems, but it seems to be working.
Regards,
Petr Sourek
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
79 | |
9 | |
9 | |
7 | |
7 | |
6 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.