Suche // Search:

Posts mit dem Label Charts werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Charts werden angezeigt. Alle Posts anzeigen

04.01.2011

FormCalc Diagramme Teil 6 - Blasendiagramm
//
FormCalc Charts Pt.6 - Bubble Chart

Heute gibt's nochmal ein neues Diagramm von mir - das Blasendiagramm (oder auch Scatter Plot genannt).
Es hat wie die vorherigen Beispiele auch die Möglichkeit Werte von 0 bis 10000 darzustellen und sich entsprechend zu skalieren.
Im Unterschied zu den bisherigen Beispielen, wird hier neben der Y-Achse auch die X-Achse dynamisch angepasst.

Zum Darstellen mehrerer Blasen, die sich ggf. auch überlappen können, wird wieder ein positioniertes Layout verwendet, bei dem mittels eines Tricks wieder mehrere Instanzen eines Teilformulars hinzugefügt bzw. gelöscht werden können.

Die Blasen zeigen jeweils den Wert für die Größe aus der Eingabetabelle an, wobei sich die Schriftgröße entsprechend der Blasengröße ändert.

Aktualierung:
Für die Blasengröße kann nun ein Mindestwert (in Zoll) angegeben werden, sodass diese im Diagramm nicht zu klein dargestellt werden.


Once more a new chart from me - the bubble chart (or scatter plot).
Like the previous examples it can display values between 0 and 10000 and scale automatically.
The diffrence in this example is, that it can dynamically adapt both, the Y and X-axis.

To display multiple bubbles which possibly can overlay each other, we use a positioned layout, where we can add or remove instances of subforms with a trick.

Each bubble shows the value of the size from the input table, where the font size changes analog to the bubble size.

Update:
For the bubble size you now can define a minimum value (inch size), so the bubble don't get rendered to small in the chart.


FormCalc-Skript – Aktualisierte Version 1.2
//
FormCalc script – Updated version 1.2
func Render(Flag) do
 if (Flag eq "true") then 
  var FactorX  
  var FactorY  
  var FactorS  
  var MaxInputX = Max(Input.Table.ChartValues[*].AmountX)
  var MaxInputY = Max(Input.Table.ChartValues[*].AmountY)
  var MaxInputS = Max(Input.Table.ChartValues[*].AmountS)
  var Fmin
  var FmaxX
  var FmaxY
  var FmaxS
  var MinPlotSize = 0.10 
  var Control = "Plotsizes:"
 
  for Fmin = 0 upto 9950 step 50 do
   FmaxX = Fmin + 50
   if (Within(MaxInputX, Fmin, FmaxX) eq 1) then
    FactorX = 1 / (FmaxX / 100)
   endif
   FmaxY = Fmin + 50
   if (Within(MaxInputY, Fmin, FmaxY) eq 1) then
    FactorY = 1 / (FmaxY / 100)
   endif
   FmaxS = Fmin + 50
   if (Within(MaxInputS, Fmin, FmaxS) eq 1) then
    FactorS = 1 / (FmaxS / 100)
   endif
  endfor
 
  var nRows = Input.Table.ChartValues.instanceManager.count 

  var GraphLabel   
  var ContainerHeight  
  var ContainerWidth   
  var ValueX
  var ValueY
  var ValueS
  var OffsetX
  var OffsetY
  var PlotSize
 
  for r=0 upto nRows -1 step 1 do
   Chart.layout = "tb"
   Chart._Plot.setInstances(nRows)
   Chart._Label.setInstances(nRows)
   Chart.layout = "position"
   ContainerHeight = UnitValue(Chart.Raster.h, "in")
   ContainerWidth = UnitValue(Chart.Raster.w, "in")
   Chart.Plot[r].y = ContainerHeight  
    
   ValueX = Input.Table.ChartValues[r].AmountX
   ValueY = Input.Table.ChartValues[r].AmountY
   ValueS = Input.Table.ChartValues[r].AmountS
   Chart.Plot[r].presence = "visible"
   Chart.Label[r].presence = "visible"

   for x = 0 upto 9 step 1 do
    Output.Chart.xAxis.Mark[x].Mark.value.text.value = Round((1 + x) * 10 / FactorX)
    Output.Chart.xAxis.y = ContainerHeight 
   endfor 
   for y = 10 downto 0 step 1 do
    Output.yAxis.Mark[y].Mark.value.text.value = Round((10 - y) * 10 / FactorY)
   endfor 

   var nColor = Choose(r+1,     
        "238,0,0",   
        "255,99,71", 
        "255,127,80",  
        "255,140,0",  
        "255,165,0",  
        "255,215,0", 
        "255,255,0",  
        "238,238,0",  
        "154,205,50",  
        "69,139,0",  
        "0,139,0",  
        "0,139,69",  
        "69,139,116",
        "82,139,139", 
        "0,139,139", 
        "0,134,139", 
        "83,134,139",
        "102,139,139", 
        "104,131,139", 
        "108,123,139") 

   Chart.Plot[r].Bubble.value.arc.edge.color.value = nColor
   Chart.Plot[r].Bubble.value.arc.fill.color.value = nColor
   Input.Table.ChartValues[r].Color.value.rectangle.fill.color.value = nColor
   GraphLabel = Input.Table.ChartValues[r].Label
   Chart.Label[r].BubbleValue.assist.toolTip.value = GraphLabel

   PlotSize = (ValueS / 150) * FactorS
   if (PlotSize >= MinPlotSize) then
    Chart.Plot[r].Bubble.h =  PlotSize
    Chart.Plot[r].Bubble.w =  PlotSize 
    Chart.Label[r].BubbleValue.h =  PlotSize
    Chart.Label[r].BubbleValue.w =  PlotSize 
   else 
    Chart.Plot[r].Bubble.h = MinPlotSize
    Chart.Plot[r].Bubble.w = MinPlotSize
    Chart.Label[r].BubbleValue.h = MinPlotSize
    Chart.Label[r].BubbleValue.w = MinPlotSize
   endif
   
   OffsetX = UnitValue(ValueX, "in") / 25.4 * FactorX  
   OffsetY = ContainerHeight - UnitValue(ValueY, "in") / 25.4 * FactorY 

   Chart.Plot[r].x =  OffsetX 
   Chart.Plot[r].y =  OffsetY 
   Chart.Label[r].x = OffsetX 
   Chart.Label[r].y = OffsetY 
   
   Chart.Label[r].BubbleValue.value.text.value = ValueS
  endfor

 endif
 RenderChart.value = "false" 
endfunc

Render(RenderChart.value)

Blasendiagramm - mit automatischer Skalierung
//
Bubble chart - with automatic scaling




Beispiel-Formular
//
Example form
https://workspaces.acrobat.com/app.html#d=71mOKqbTBCQOGuBLaSBndg

22.12.2010

FormCalc Diagramme Teil 4-V2 - Liniendiagramm
//
FormCalc Chart Pt.4-V2 - Line Charts

Liniendiagramme sind alles andere als einfach in Designer herzustellen, aber dass es geht habe ich ja schon vor einiger Zeit gezeigt.
Die Version hatte allerdings einige Einschränkungen.
So mussten alle möglicherweise genutzten Liniem schon während der Design-Phase eingefügt werden, da es nur mit einem positionierten Layout möglich ist, Element übereinander zu legen.
Mittels eines Tricks ist das nun nicht mehr nötig.
Dafür genügen schon 4 Zeilen Code.
Kurz gesagt, sagen wir dem Formular erst, dass das Teilformular "Chart" fließend ist, was uns ermöglich von den eingeschlossenen Teilformulare "Line" und "Label" neue Instanzen anzulegen.
Dannach wird das Teilformular einfach wieder auf positioniert gesetzt, fertig.

Chart[j].layout = "tb"
Chart[j]._Line.setInstances(nRows)
Chart[j]._Label.setInstances(nRows)
Chart[j].layout = "position"

Des Weiteren ist das Diagramm auch nicht mehr auf einen kleine Darstellungsbereich beschränkt.
Mittels eines Faktors kann es Werte zwischen 0 und 10.000 dynamisch darstellen.


Line Charts aren't easy to realize in Designer, but a while ago I showed that it is still possible.
Well that version hat some restrictions.
One was, that all possibly used lines already had to added in the design phase, because only a positioned layout allows to lay element on top of each other.
With a small trick this isn't neccessary anymore.
Four lines of code are enough to do this.
In short, we tell the form that the subform "Chart" is flowing, which allows us to add more instances of the wrapped subforms "Line" und "Label".
After that, we reset the subform to positioned, done!

Chart[j].layout = "tb"
Chart[j]._Line.setInstances(nRows)
Chart[j]._Label.setInstances(nRows)
Chart[j].layout = "position"

Aditionally it is now possible to use the chart in a large value range.
With the use of a factor ist can display values between 0 and 10.000 dynamically.



Alte Hierarchie des Formulars - Jedes eventuell benötigte Objekt muss bereits vorhanden sein
//
Old hierarchy of the form - Every possibly needed object has to be already present

Neue Hierarchie des Formulars - Jedes Objekt ist erstmal nur einmalig vorhanden
//
New hierarchy of the form - Every object initially occurs only once


Neues FormCalc-Skript
//
New FormCalc script

var Check = RenderChart.value
if (Check eq "true") then
var Factor
var MaxInput = Max(Input.Table.ChartValues[*].Col[*].Amount)
var Fmin
var Fmax
for f = 0 upto 9950 step 50 do
Fmin = f
Fmax = Fmin + 50
if (Within(MaxInput, Fmin, Fmax) eq 1) then
Factor = 1 / (Fmax / 100)
endif
endfor

var nRows = Input.Table.ChartValues.instanceManager.count
var nColumns = Input.Table.ChartValues[nRows -1].Col.instanceManager.count
_Chart.setInstances(nColumns + 1)

var GraphValue
var GraphLabel
var PrevGraphValue
var GraphDiff
var LineStart
var ContainerHeight
var Offset

for r=0 upto nRows -1 step 1 do
for c=0 upto nColumns -1 step 1 do
Chart[c].layout = "tb"
Chart[c]._Line.setInstances(nRows)
Chart[c]._Label.setInstances(nRows)
Chart[c].layout = "position"
ContainerHeight = UnitValue(Chart[c].hLines.h, "in")
Chart[c].Line[r].y = ContainerHeight
GraphValue = Input.Table.ChartValues[r].Col[c].Amount
Chart[c].Line[r].presence = "visible"
Chart[c].Label[r].presence = "visible"
Chart[0].Line[r].presence = "invisible"

if(c eq 0) then
PrevGraphValue = 0
LineStart = ContainerHeight
else
PrevGraphValue = Input.Table.ChartValues[r].Col[c-1].Amount
LineStart = UnitValue(Chart[c-1].Line.LineGraph.y, "mm")
endif

for y = 10 downto 0 step 1 do
Output.yAxis.Mark[y].Mark.value.text.value = Round((10 - y) * 10 / Factor)
endfor

var nColor = Choose(r+1, ;Instance (+1) = position in this list
"238,0,0", ;Red
"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
"69,139,0", ;Chartreuse
"0,139,0", ;Green
"0,139,69", ;SpringGreen
"69,139,116", ;Aquamarine
"82,139,139", ;DarkSlateGray
"0,139,139", ;Cyan
"0,134,139") ;Turquoise
Chart[c].Line[r].LineGraph.value.line.edge.color.value = nColor
Input.Table.ChartValues[r].Color.Color.value.rectangle.fill.color.value = nColor

GraphDiff = GraphValue - PrevGraphValue
Chart[c].Line[r].LineGraph.h = UnitValue(Abs(GraphDiff), "in") / 25.4 * Factor
Chart[c].Label[r].LineValue.value.text.value = GraphValue
GraphLabel = Input.Table.ChartValues[r].Label
Chart[c].Label[r].LineValue.assist.toolTip.value = GraphLabel

if(GraphDiff >= 0) then
Chart[c].Line[r].LineGraph.value.#line.slope = "/"
else
Chart[c].Line[r].LineGraph.value.#line.slope = "\"
endif

if(c eq 0) then
Offset = ContainerHeight - UnitValue(Abs(GraphDiff), "in") / 25.4 * Factor
Chart[c].Line[r].y = Offset
Chart[c].Label[r].y = Offset
else
if(GraphDiff >= 0) then
Offset = ContainerHeight - GraphValue / 25.4 * Factor
Chart[c].Line[r].y = Offset
Chart[c].Label[r].y = Offset
else
Offset = ContainerHeight - (GraphValue + Abs(GraphDiff)) / 25.4 * Factor
Chart[c].Line[r].y = Offset
Chart[c].Label[r].y = ContainerHeight - (GraphValue / 25.4) * Factor
endif
endif
endfor
endfor
endif
RenderChart.value = "false"




Liniendiagramm - mit automatischer Größenanpassung
//
Line chart - with auto-resizing


Beispiel // Example
https://files.acrobat.com/a/preview/a3e6c8e5-5311-4219-a6f7-d7a2f2259d50

20.12.2010

FormCalc Diagramme Teil 5 - Automatisch vergrößerndes, gestapeltes Säulendiagramm
//
FormCalc Charts Pt.5 - Auto-resizing, stacked Bar Charts

Dies ist eine Weiterentwicklung von dem gestapelten Säulendiagramm, dass ich vor einiger Zeit geposted habe.
Bei dem alten Beispiel störte mich die Beschränkung auf einen bestimmten Wertebereich.
War dieser nicht ausreichend groß dimensioniert, wuchs das Diagramm mitunter oben aus dem Darstellungsbereich heraus.

Mit einer kleinen Ergänzung im Berechnungsalgoritmus ist dies nun aber kein Problem mehr.

Mittels eines Faktors kann der Wertbereich beliebig groß definiert werden.
Dafür prüft eine For-Schreife, ob das größte aller Gesamtergebnisse innerhalb eines bestimmten Bereichs liegt.
Trifft dies zu, wird dann ein Faktor anhand dieses Wertes berechnet, der später in die Berechnung der Balken einbezogen wird.

Des Weiteren wird eine Formularvariable "RenderChart" verwendet, die verhindert, dass der Trigger das Diagramm auch neu berechnet, wenn gar keine Änderung an den Eingabedaten vorliegt.
Mit einem If-Ausdruck wird das ganze Berechnungsskript umfasst und nur dann ausgeführt, wenn die Formvariable den Wert "true" hat.


This is an upgrade of the stacked bar chart I've posted a while ago.
In this old example I get bothered by the limitation of the range of values.
If it was to small the chart began to grow out of the displaying area.

But, with a small addition to the algorithm I was able to solve this problem.

With the use of a factor the range of values can be as large as you like.
Therefor a for-loop is used, which checks if the largest of all total results is within a specific range.
If so, the factor will be calculated by this value and later reused to calculate the bars.

In addition a form variable "RenderChart" is used to suppress a recalculation of the charts if there has been no changes to the input values.
With an if-expression which surrounds the whole calculation script, the script is only executed if the form variable has the value "true".

FormCalc-Skript
//
FormCalc script:

var Check = RenderChart.value
if (Check eq "true") then
var Factor
var MaxInput = Max(Input.Table.ChartValues[*].Sum)
var Fmin
var Fmax
for f = 0 upto 9950 step 50 do
Fmin = f
Fmax = Fmin + 50
if (Within(MaxInput, Fmin, Fmax) eq 1) then
Factor = 1 / (Fmax / 100)
endif
endfor

var nRows = Input.Table.ChartValues.instanceManager.count
_Chart.setInstances(nRows)
var nColumns = Input.Table.ChartValues[nRows -1].Col.instanceManager.count
Chart[*].Stack._Bar[*].setInstances(nColumns)
Chart[*].Labels._Label[*].setInstances(nColumns)

for i=0 upto nRows -1 step 1 do
for j=0 upto nColumns -1 step 1 do
var BarValue = Input.Table.ChartValues[i].Col[j].Amount
for y = 10 downto 0 step 1 do
Output.yAxis.Mark[y].Mark.value.text.value = Round((10 - y) * 10 / Factor)
endfor

var nColor = Choose( j + 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
Chart[i].Stack.Bar[j].BarGraph.value.rectangle.fill.color.value = nColor
Chart[i].Stack.Bar[j].BarGraph.value.rectangle.edge.color.value = nColor

if (BarValue > 0) then
Chart[i].Stack.Bar[j].presence = "visible"
else
Chart[i].Stack.Bar[j].presence = "invisible"
endif

var ChartMod = UnitValue(BarValue, "in") / 25.4
Chart[i].Stack.Bar[j].BarGraph.h = UnitValue(ChartMod, "in") * Factor
Chart[i].Labels.Label[j].BarValue.h = UnitValue(ChartMod, "in") * Factor
Chart[i].Labels.BarTotal = Input.Table.ChartValues[i].Sum
Chart[i].Labels.BarLabel = Input.Table.ChartValues[i].Label

if(BarValue * Factor >= 3) then
Chart[i].Labels.Label[j].BarValue.value.text.value = Input.Table.ChartValues[i].Col[j].Amount
else
Chart[i].Labels.Label[j].BarValue.value.text.value = ""
endif

var ContainerHeight = UnitValue(Chart.h, "in")
var MoveHeight = UnitValue(Input.Table.ChartValues[i].Sum, "in") / 25.4 * Factor
Chart[i].Stack.y = ContainerHeight - MoveHeight
Chart[i].Labels.y = ContainerHeight - MoveHeight - UnitValue("5mm", "in")
endfor
endfor
endif


Beispiele gestapelter Balkendiagramme
//
Stacked Bar Charts Examples

Wertebereich 0 - 150 // Range of values 0 - 150


Wertebereich 0 - 550 // Range of values 0 - 550



Wertebereich 0 - 1300 // Range of values 0 - 1300




Bespiel-Formular
//
Sample form:
https://files.acrobat.com/a/preview/d9eaad0a-fea0-4303-8fd4-74a24fadb6fc


11.05.2010

FormCalc Diagramme Teil 4 - Liniendiagramm
//
FormCalc Charts Pt.4 - Line Chart

Ein Liniendiagramm ist ja der Klassiker schlechthin unter den Diagrammen.
Aber, um dieses Diagramm mit dem LiveCycle Designer herzustellen, ist etwas Aufwand nötig, da sich die Instanzen (sprich Graphen) ja überlagern können müssen.
Mit der Möglichkeit Teilformulare dynamisch hinzuzufügen und zu löschen kommt man hier also nicht weit, da sich die Instanzen in XFA-Formularen nur von links nach rechts oder oben nach unten anordnen.

Also muss hier alles, was evtl. angezeigt werden wird, schon im Formularlayout vorhanden sein.
Den Rest kann dann wieder ein einzelnes FormCalc-Script übernehmen.


The line chart is a real classic.
But, to realize it with LiveCycle Designer you need to expend effort.
That's because all instances (graphs) should be able to overlap each other.
Working with repeating subforms in XFA-forms won't work here, because these are only arraged next to each other from top to buttom or left to right and not on top of each other.

So, everything that could be shown later in the chart has to be in the form layout from the beginning.
The rest than could be done by a single FormCalc script.

FormCalc Script (sorry, sript looks a bit unpretty, because this blog editor has it's own life!):


var nRows = Input.Table.ChartValues.instanceManager.count 
var nColumns = Input.Table.ChartValues[nRows -1].Col.instanceManager.count 
_Chart.setInstances(nColumns)
var GraphValue
var GraphLabel
var PrevGraphValue
var GraphDiff
var GraphMod
var LineStart
var ContainerHeight = UnitValue(Chart.h, "in")
var Offset 

for i=0 upto nRows -1 step 1 do
for j=0 upto nColumns -1 step 1 do
if(j == 0) then
GraphValue = Input.Table.ChartValues[i].Col[j].Amount
PrevGraphValue = 0
LineStart = UnitValue(Chart[j].h, "in")
else
GraphValue = Input.Table.ChartValues[i].Col[j].Amount
PrevGraphValue = Input.Table.ChartValues[i].Col[j-1].Amount
LineStart = UnitValue(Chart[j-1].Line.LineGraph.y, "mm")
endif
Chart[j].Line[i].presence = "visible"
Chart[j].Label[i].presence = "visible"

;Select a color for the lines
var nColor = Choose(i+1,
"238,0,0",
"255,99,71",
"255,127,80",
"255,140,0",
"255,165,0",
"255,215,0",
"255,255,0",
"238,238,0",
"154,205,50",
"69,139,0",
"0,139,0",
"0,139,69",
"69,139,116",
"82,139,139",
"0,139,139",
"0,134,139")

Chart[j].Line[i].LineGraph.value.line.edge.color.value = nColor
Input.Table.ChartValues[i].Color.Color.value.rectangle.fill.color.value = nColor

GraphDiff = GraphValue - PrevGraphValue
Chart[j].Line[i].LineGraph.h = UnitValue(Abs(GraphDiff), "in") / 25.4
Chart[j].Label[i].LineValue.value.text.value = GraphValue
GraphLabel = Input.Table.ChartValues[i].Label
Chart[j].Label[i].LineValue.assist.toolTip.value = GraphLabel

if(GraphDiff >= 0) then
Chart[j].Line[i].LineGraph.value.#line.slope = "/"
else
Chart[j].Line[i].LineGraph.value.#line.slope = "\"
endif

if(j == 0) then
Offset = ContainerHeight - UnitValue(Abs(GraphDiff), "in") / 25.4
Chart[j].Line[i].y =  Offset
Chart[j].Label[i].y = Offset 
else
if(GraphDiff >= 0) then
Offset = ContainerHeight - GraphValue / 25.4
Chart[j].Line[i].y = Offset
Chart[j].Label[i].y = Offset
else
Offset = ContainerHeight - (GraphValue + Abs(GraphDiff)) / 25.4 
Chart[j].Line[i].y = Offset 
Chart[j].Label[i].y = ContainerHeight - (GraphValue / 25.4) 
endif
endif
endfor
endfor


Liniendiagramm // Line Chart:


Bespiel // Example:
https://files.acrobat.com/a/preview/34a5dfb2-392b-41e3-959d-11536d9a9b22

09.04.2010

FormCalc Diagramme Teil 3 - Gestapeltes Säulendiagramm
//
FormCalc Charts Pt.3 - Stacked Bar Charts

Dies ist ein Upgrade zum einfachen Säulendiagramm von neulich.
Hier werden nun aus verschiedenen Eingabewerten gestapelte Säulendiagramme generiert.
Dafür kommt eine Tabelle zum Einsatz, die es erlaubt sowohl Zeilen als auch Spalten hinzuzufügen.
Die Kalkulation der Säulen übernimmt auch hier ein verstecktes Feld "Trigger", dass mit FomCalc arbeitet.

This is an Upgrade of the simple bar chart I posted on the other day.
This one generates stacked bar charts from the input values.
Therefore it uses a table that allows to add rows and columns.
The calculations of the bars is done by a hidden field "trigger" with a FormCalc script.

FormCalc Script:
var nRows = Input.Table.ChartValues.instanceManager.count

_Chart.setInstances(nRows)
var nColumns = Input.Table.ChartValues[nRows -1].Col.instanceManager.count
Chart[*].Stack._Bar[*].setInstances(nColumns)
Chart[*].Labels._Label[*].setInstances(nColumns)


for i=0 upto nRows -1 step 1 do
for j=0 upto nColumns -1 step 1 do
var BarValue = Input.Table.ChartValues[i].Col[j].Amount


var nColor = Choose(j+1, "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
Chart[i].Stack.Bar[j].BarGraph.value.rectangle.fill.color.value = nColor
Chart[i].Stack.Bar[j].BarGraph.value.rectangle.edge.color.value = nColor


var ChartMod = UnitValue(BarValue, "in") / 25.4
Chart[i].Stack.Bar[j].BarGraph.h = UnitValue(ChartMod, "in")
Chart[i].Labels.Label[j].BarValue.h = UnitValue(ChartMod, "in")
Chart[i].Labels.BarTotal = Input.Table.ChartValues[i].Sum
Chart[i].Labels.BarLabel = Input.Table.ChartValues[i].Label

if(Input.Table.ChartValues[i].Col[j].Amount >= 3) then
Chart[i].Labels.Label[j].BarValue.value.text.value = Input.Table.ChartValues[i].Col[j].Amount
else
Chart[i].Labels.Label[j].BarValue.value.text.value = ""
endif


var ContainerHeight = UnitValue(Chart.h, "in")
var ChartOffset = UnitValue(Input.Table.ChartValues[i].Sum, "in") / 25.4
Chart[i].Stack.y = ContainerHeight - ChartOffset
Chart[i].Labels.y = ContainerHeight - ChartOffset - UnitValue("5mm", "in")
endfor
endfor
Gestapeltes Säulendiagramm // Stacked Bar Chart:


Beispiel
//
Example:
https://files.acrobat.com/a/preview/2d351f73-093f-44fa-9881-2fbb04ed3dc8

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

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: