Suche // Search:

25.03.2010

FormCalc Diagramme Teil 2 - Tortendiagramme (V1 & V2)
//
FormCalc Charts Pt.2 - Pie Charts (V1 & V2)

In der Vergangenheit habe ich schon einige Arten an Diagrammen entwickelt, die sich mit FormCalc innerhalb eines XFA-Formulars erstellen und bearbeiten lassen.
Da war eigentlich alles dabei, nur kein Tortendiagramm.
Das liegt an den sehr beschränkten Manipulationsmöglichkeiten für Kreise im LiveCycle Designer.
Ich habe nun aber eine Möglichkeit gefunden, wie man solche Diagramme doch erstellen kann.
Das ist zwar sehr experimentell aber es funktioniert.
Nur ist es sehr konstruktionsbedingt sehr ressourcenhungrig.

Für die Eingabe verwende ich eine Tabelle.
Für das Diagramm verwendet ich Bogenlinien, und zwar einige hundert davon.
Damit lässt sich ein mehrfarbiger Kreis simulieren.
Die Berechnung erfolgt über ein verstecktes Feld "Trigger", dass alle Bögen per for-Schleife ansteuert und deren Position, Länge und Farbe berechnet.

Je nach Anzahl der Eingabewerte sind dadurch mehrere Tausend Bögen zu berechnen, was die Berechnung mitunter stark verlangsamt.

In the past I already developed several kinds of charts with FormCalc that could be used in a XFA-form.
Only a pie chart was missing, because of the very limited capabilities of manipulation of cicles in LiveCycle Designer.
Now I fould a way to do this.
It's very experimental but it works so far.

For the data input I use a table and for the pie several hundred bows.
This bows simulate a multicolored cicle.
The calculation is done by a hidden field "trigger" that uses a for-loop to calculate the positions, legths and colors of every bow.

Depending on the number of values in the table, the script has to calculate thousands of bows so it becomes slower.

FormCalc-Skript – Version 1
//
FormCalc-Skript – Version 1
var nCharts = Input.Table.ChartValues.instanceManager.count
for i=0 upto nCharts -1 step 1 do
 var PieValue = Input.Table.ChartValues[i].Amount
 if(PieValue >= 0) then
  var Total = 0
  for j = 0 upto nCharts -1 do
   Total = Total + Input.Table.ChartValues[j].Amount
  endfor

  var Weighting = Round(100 / Total * PieValue, 2)
  var OneDegree = Round(360 / 100, 1)
  var Sweep = Weighting * OneDegree
  var StartDegree = 0
  Pie[i].Bow[*].value.arc.sweepAngle = Sweep

  if(i eq 0) then
   Pie[i].Bow[*].value.arc.startAngle = StartDegree
  elseif(i > 0) then
   StartDegree = Pie[i-1].Bow.value.arc.startAngle + Pie[i-1].Bow.value.arc.sweepAngle
   Pie[i].Bow[*].value.arc.startAngle = StartDegree
  endif

  var nColor = Choose(i+1, ;Instance (+1) = position in this list
    "238,0,0", ;Red
    "255,48,48", ;FireBrick
    "255,99,71", ;Tomato
    "255,127,80", ;Coral
    "255,140,0", ;DarkOrange
    "255,165,0", ;Orange
    "255,215,0", ;Gold
    "255,255,0", ;Yellow
    "238,238,0", ;Yellow2
    "154,205,50") ;YellowGreen

  Pie[i].Bow[*].value.arc.edge.color.value = nColor
  Input.Table.ChartValues[i].Color.Color.value.rectangle.fill.color.value = nColor
 endif
endfor

Tortendiagramm  – Version 1
//
Pie Chart – Version 1


Beispiel & XML-Daten – Version 1
//
Example & XML-Data  – Version 1
https://workspaces.acrobat.com/?d=8ISRovhkYV2lD9Fb5q1yPA
https://workspaces.acrobat.com/?d=aLgtLEY54EfFuWl02xeLMA


Aktualisierung: Die Version 2 bietet etwas mehr Flexibilität.
Zum einen braucht in Designer nun nur noch eine Instanz des Bogens vorhanden sein, da alle weiteren Instanzen über das Skript ermittelt und hinzugefügt werden.
Des Weiteren kann nun die Größe des Diagramms, des Lochs in der Mitte, sowie die Linienstärke je Bogen , der Abstand der Bögen zueinander und der Winkel verändert werden.

Je dünner die Bögen und je kleiner der Abstand zwischen den Bögen, desto besser sieht das Diagramm aus.
Aber, je nach Anzahl der Bögen im Diagramm ist der Berechnungsaufwand beträchtlich.
Seien Sie also vorsichtig damit.

Update: Version 2 offers more flexibility.
On the one hand you only need to define one instance of the bow in Designer because the script will determine and add all the rest.
On the other hand you can define the size of the chart, the hole in the middle, the line thickness of the bows and the gaps between them and even the angle by yourself.

Thinner the bows and and gaps will make the chart looking even better.
But, depending on the number of bows the overhead of calculations can be come extremly high.
So be careful.


FormCalc-Skript – Version 2 
//
FormCalc-Skript – Version 2 
var nCharts = Input.Table._ChartValues.count  
var MaxSize = 30         
var GapSize = 0.5         
var Line = 0.5          
var Hole = Round(20 / Sum(Line, GapSize)) 
var Bows = Round(MaxSize / GapSize) - Hole 
var Angle = 0
var Total = Sum(Input.Table.ChartValues[*].Amount) 

func SetBows(nPie, nBow) do
 if (Pie[nPie]._Bow.count ne nBow) then
  Pie[nPie].layout = "tb"
     Pie[nPie]._Bow.setInstances(nBow)
     Pie[nPie].layout = "position"
    endif
endfunc

func SetPies(nChart) do
 if (Output._Pie.count ne nChart) then
  Output.layout = "tb"
     Output._Pie.setInstances(nChart)
     Output.layout = "position"
    endif
endfunc

func ModifyBows(nPie, Bows, MaxSize, GapSize) do
 for m = Bows -1 downto 0 step 1 do
  var Diameter = GapSize * m 
  var Offset = Diameter / 2
  var NewDiameter = Concat(MaxSize - Diameter, "mm")
  var NewOffset = Concat(Offset, "mm")
  Pie[nPie].Bow[m].Bow.h = NewDiameter
  Pie[nPie].Bow[m].Bow.w = NewDiameter
  Pie[nPie].Bow[m].Bow.x = NewOffset
  Pie[nPie].Bow[m].Bow.y = NewOffset
 endfor
endfunc

func CalcPies(nPie, nPieValue, nCharts, Total, Bows, Angle) do
 if(nPieValue ge 0) then
  var Weighting = Round(100 / Total * nPieValue, 2)
  var Sweep = Weighting * 3.6
  Pie[nPie].Bow[*].Bow.value.arc.sweepAngle = Sweep 
  var StartAngle = Angle
  if(nPie eq 0) then
   Pie[nPie].Bow[*].Bow.value.arc.startAngle = StartAngle
  elseif(nPie gt 0) then
   StartAngle = Sum(Pie[nPie-1].Bow[0].Bow.value.arc.startAngle, Pie[nPie-1].Bow[0].Bow.value.arc.sweepAngle)
   Pie[nPie].Bow[*].Bow.value.arc.startAngle = StartAngle
  endif
 endif
endfunc

func ShapePies(nPie, Line) do
 var nColor = Choose(nPie+1,  
       "255,255,0",   
       "255,211,13",  
       "255,161,0",  
       "255,107,13",  
       "255,32,0",  
       "255,13,130",  
       "200,0,255",  
       "83,13,255",  
       "0,51,255",  
       "13,177,255",
       "0,255,212",
       "13,255,89",
       "62,255,0",
       "149,255,13",
       "255,217,0")  
 
 Pie[nPie].Bow[*].Bow.value.arc.edge.color.value = nColor
 Pie[nPie].Bow[*].Bow.value.arc.edge.thickness = UnitValue(Concat(Line,"mm"), "in")
 Input.Table.ChartValues[nPie].Color.Color.value.rectangle.fill.color.value = nColor
endfunc

if (RenderChart.value eq 1) then
 for n=0 upto nCharts -1 step 1 do
  var nPieValue = Input.Table.ChartValues[n].Amount
  SetPies(nCharts)
  SetBows(n, Bows)
  ModifyBows(n, Bows, MaxSize, GapSize)
  CalcPies(n, nPieValue, nCharts, Total, Bows, Angle)
  ShapePies(n, Line)
 endfor
RenderChart.value = 0
endif

Tortendiagramm  – Version 2 mit variabler Größe, Bogenanzahl und Winkel
//
Pie Chart – Version 2 with variable size, bow number and angle





Beispiel – Version 2
//
Example  – Version 2
https://files.acrobat.com/a/preview/78c3b72c-f81c-47fd-84f4-1078630963b7

16.03.2010

Formulare mit RC4 verschlüsseln
//
Encrypt Forms with RC4

Basierend auf dem Beispiel Base64 Encryption habe ich ein anderes Beispiel entwickelt, das anstelle von Base64 den Rivest Cipher No.4 Algorythmus (RC4) verwendet.

Der Algorythmus arbeitet innerhalb XFA-Formularen zwar, benötigt aber zuvor etwas Feinschliff.
Damit es beim Verschlüsseln und Entschlüsseln nicht zur Fehler kommt, die dazu führen, dass der Text abgeschnitten wird oder bestimmte Schriftzeichen fehlerhaft verarbeitet werden, muss der eigentliche Algorithmus mit der escape() bzw. unescape() Funktion kombiniert werden.

Für einen möglichst hohen Verschlüsselungsgrad wird aus dem Password des Benutzers ein Hashwert generiert, der mit einem anderen Hashwert kombiniert wird, das sogenannte Salting.
Aus diesem wird dann wiederum ein Hashwert erzeugt, der letzlich zur Ver- und Entschlüsselung verwendet wird.

Based on the example for the Base64 Encryption I developed another example, that uses the Rivest Cipher No. 4 algorithm (RC4).

To work proper in XFA-forms the algorithm needs some final touch.
Otherwise it will produces errors like cuf off text and misinterpreted characters when encrypting oder decrypting the text strings.
Therefore I added the escape() repectively unescape() functions to the algorithm for the enryption and decryption.

For a high ciphering level the form generates a hash-key from the users password which then will be combined with another hash-key (the so-called Salting). From this salted hash-key there will be generated a final hash-key which is used for the en- and decryption.


JavaSript für Verschlüsselung // JavaScript for Encryption:

var CharSetSize = 256;
var RC4_SubstitutionBox = new Array(CharSetSize);


function RC4_crypt (KeyWord, InputTextString)
{
var i, j, k = 0;
var Temp = 0;
var t = 0;
var ModifiedText = "";


for (j = 0; j < CharSetSize; j++)
RC4_SubstitutionBox[j] = j;
j = 0;


for (i=0; i < CharSetSize; i++)
{
j = (j + RC4_SubstitutionBox[i] + KeyWord.charCodeAt(i % KeyWord.length)) % CharSetSize;
Temp = RC4_SubstitutionBox[i];
RC4_SubstitutionBox[i] = RC4_SubstitutionBox[j];
RC4_SubstitutionBox[j] = Temp;
}


for (k=0; k < InputTextString.length; k++)
{
i = (i + 1) % CharSetSize;
j = (j + RC4_SubstitutionBox[i]) % CharSetSize;
Temp = RC4_SubstitutionBox[i];
RC4_SubstitutionBox[i] = RC4_SubstitutionBox[j];
RC4_SubstitutionBox[j] = Temp;
t = (RC4_SubstitutionBox[i] + RC4_SubstitutionBox[j]) % CharSetSize;
ModifiedText = ModifiedText + String.fromCharCode(InputTextString.charCodeAt(k) ^ RC4_SubstitutionBox[t]);
}
return escape(ModifiedText);
}
Klartext // Cleartext:



RC4-verschlüsselter Text // RC4-Encrypted Text:


Beispiel // Example:
https://acrobat.com/#d=35uUne9Hl5V*fZG8ZRWLBA

14.03.2010

FormCalc Diagramme Teil 1 - Säulendiagramm
//
FormCalc Charts Pt.1 - Bar Charts

Ein riesen Manko am LiveCycle Designer ist, dass er keine Diagramme aus den Formulardaten erstellen kann, so wie das Excel kann.
Mit etwas Einsatz vom FormCalc, kann man dies aber (schnell) beseitigen.
Dieses Beispiel ist eine Weiterentwicklung des Scripts, dass ich vor knapp einem Jahr im Acrobatusers.com-Forum geposted habe.

Es besteht aus einer Tabelle zum Eingeben der Daten (Beschreibung und Wert sowie Farbe) und einem Teilformular mit einem verstecktem Feld, dass die Diagramme per FormCalc quasi in Echtzeit berechnet.

One of LiveCycle Designers flaws is, that it can't generate chart from the form data such as Excel does.
But with some FormCalc experiences this can be solved.
This example is a new version of a script I posted about a year ago in the Acrobatusers.com community.

It contains a table for the inputs (label, value and color) and a subform with a hidden field that calculates the chart quasi in realtime.

FormCalc-Script:

var nCharts = Input.Table.ChartValues.instanceManager.count

_Chart.setInstances(nCharts)

var CurrentInstance = $.parent.index
var ChartValue = Input.Table.ChartValues[CurrentInstance].Amount
var ChartLabel = Input.Table.ChartValues[CurrentInstance].Label.value.text.value
var ChartColor = Input.Table.ChartValues[CurrentInstance].Color.value.text.value
var ChartMod = UnitValue(ChartValue / 25.4)
var Maximum = UnitValue(105 / 25.4)

if(ChartMod > Maximum) then
ChartMod = Maximum
zLine.presence = "visible"
elseif(ChartMod <= Maximum) then
zLine.presence = "invisible"
endif


var ChartMove = Round(UnitValue(ChartMod * 25.4))
var ContainerHeight = Round(UnitValue(Output.Chart.h))
var ChartStart = ContainerHeight
var ChartEnd = ChartStart - ChartMove

if (ChartValue >= 0) then
Bar.presence = "visible"
Bar.h = ChartMod
Bar.y = UnitValue(ChartEnd / 25.4 )
BarValue.value.text.value = ChartValue
BarValue.y = UnitValue(ChartEnd / 25.4 )
BarLabel.presence = "visible"
BarLabel.value.text.value = ChartLabel
BarLabel.y = UnitValue(ChartEnd / 25.4 )

if(ChartColor == "O")then
Bar.value.rectangle.fill.color.value = "255,153,0"
elseif(ChartColor == "R") then
Bar.value.rectangle.fill.color.value = "255,0,0"
elseif(ChartColor == "B") then
Bar.value.rectangle.fill.color.value = "0,0,255"
elseif(ChartColor == "G") then
Bar.value.rectangle.fill.color.value = "0,255,0"
endif

else
Bar.presence = "invisible"
Bar.presence = "invisible"
BarLabel.presence = "invisible"
endif

Säulendiagramm // Bar Chart:


Beispiel // Example:

13.03.2010

Formulare mit Base64 verschlüsseln
//
Encrypt Forms with Base64

Haben Sie schon mal ein PDF-Formular gehabt, dessen Inhalt sie verschlüsseln können?
Ich auch nicht. Warum eigentlich nicht?
Es kann doch nur praktisch sein, die Inhalte einer PDF zu verschlüsseln anstatt die PDF als solche.
Schließlich gibt es mittlerweile diverse Tools, die die Passwortschale einer PDF in Sekunden knacken.

Also warum nicht die PDF offen lassen und den Inhalt unleserlich machen?

Dieses Beispiel-Formular verwendet ein Script zum Verschlüsseln der Daten als Base64-String.
Das Ganze wird durch eine Passwortabfrage gesichert, die Hashwerte aus den Eingaben erstellt und vergleicht.

Have you ever seen a PDF form where you could encrypt the contents?
I didn't, but why?
It will be so handy to encrypt the content instead of the whole file.
Because there are so many cracking tools around, that will break the password shell within seconds.

So why don't leave file open and make the contents unreadable?

The example form uses a script to encrypt the data as base64 string, protected by a password query that uses hashes and compares them.

Klartext
//
Cleartext:

Base64-verschlüsselter Text
//
Base64-encrypted Text:



Beispielformular
//
Sample form:
https://files.acrobat.com/a/preview/84c26bcc-68f0-43a3-b1e6-4f07c7dd5d6e