Adobe InDesign: Drucken von DIN A5 Faltheftchen

Aufgabenstellung

Es soll ein Din A5 Faltheftchen mit Adobe InDesign erstellt werden, welches auf dem Heimdrucker ausgedruckt werden kann.

Voreinstellungen

Zunächst wird ein Dokument mit den Maßen für Din A5 (Document Setup) erstellt:

Problem 1

Als erstes muss klar sein, das ein A5 Heftchen aus gefalteten DIN A4 Blättern besteht. Jedes DIN A4 Blatt wird beidseitig bedruckt und bietet Platz für 4 DIN A5 Seiten.

Lösung 1

Also sollte die Seitenanzahl durch 4 teilbar sein, bevor man druckt, damit man nicht anfangen muss zu kleben und zu basteln. Ein Dokument hat idealerweise eine Seitenzahl von n=4*x (x:DIN A4 Blätter). Unbenutzte Seiten können mit Bildchen und anderen Platzauffüllern besetzt werden.

Problem 2

Viele Drucker haben keine Duplex-Einheit für den beidseitigen Druck.

Lösung 2

Hierfür muss eine Treibereinstellung des Druckertreibers genutzt werden (beidseitiger Druck auf manuell), der zunächst alle ungeraden Seiten druckt, und danach auffordert den Papierstapel erneut wie gedruckt (mit der Schrift nach oben) einzulegen. Das Betätigen des Weiter-Buttons druckt anschließend die geraden Seiten aus.
Hierfür empfehle ich die normale Print-Option (nicht Print Booklet) zu verwenden. Es muss lediglich auf die Seitenzahl (Problem 1) geachtet werden und leere Seiten mit Platzhaltern aufgefüllt werden.

Beispiel-Dokument

Folgendes Kirchenheft wurde mit 8 Seiten mit InDesign CS4 erstellt und als DIN A5-Booklet über die normale Print-Option gedruckt:
Beispiel Dokument

HTML5: Mit Canvas malen

Aufgabenstellung

In einem HTML 5 Canvas soll über JavaScript-Events die Mausposition ausgelesen, und an dieser gemalt werden.

Ansatz

Verwendung der Events onmousedown, onmouseup, onmousemove des Canvas-Elements. Nutzung der clientX- und clientY-Eigenschaft

Prämissen / Vorraussetzungen

Es wird ein aktueller Browser verwendet, der das HTML 5 Canvas-Element unterstützt.

Lösung

<html>
<head>
<script>
	function draw() {
		var canvas = document.getElementById("canvas");
		var ctx = canvas.getContext("2d");
		ctx.fillStyle = "black";
		ctx.beginPath();
		var x;
		var y;
		canvas.onmousedown = function(e) {
			x = e.clientX;
			y = e.clientY;
			ctx.moveTo(x, y);
		}
		canvas.onmouseup = function(e) {
			x = null;
			y = null;
		}
		canvas.onmousemove = function(e) {
			if (x == null || y == null) {
				return;
			}
			x = e.clientX;
			y = e.clientY;
			x -= canvas.offsetLeft;
			y -= canvas.offsetTop;
			ctx.lineTo(x, y);
			ctx.stroke();
			ctx.moveTo(x, y);
		}
	};
</script>
</head>
<body onload="draw();">
	<canvas id="canvas" width="300" height="300"
		style="border: 1px solid black;"></canvas>
</body>
</html>

MS SQL Server: DROP TABLE wenn die Tabelle nicht existiert

Aufgabenstellung

Eine Tabelle soll gelöscht werden wenn sie existiert.

Problem

Nutzt man in einem TSQL-Skript den DROP Table Befehl (z.B. in einer Stored Procedure) erhält man eine Fehlermeldung, das die zu löschende Tabelle nicht existiert. In einigen Fällen führt dies zum Abbruch des Skriptes.

Ansatz

Über das META-Schema vom MS SQL Server lässt sich erfragen, ob eine Tabelle existiert.

Lösung

IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'users') 
DROP TABLE users;

MS SQL Server und ACCESS: Führende Nullen in numerischem String abschneiden

Aufgabenstellung

In einer Spalte mit Materialnummer/Artikelnummern werden bei allen numerischen Materialnummern die Nullen entfernt, alphanumerische Materialnummern bleiben unberührt. Soll auch bei den alphanumerischen Materialnummern die führenden Nullen entfernt werden, verweise ich auf den Artikel in der Rubrik „MS SQL Server: Führende Nullen bei alphanumerischem String“.

Ansatz

Über das Case Statement wird gefragt ob der Artikel numerisch ist. Ist er numerisch, wird über die Konvertierung in einen Integer (und anschließendes Zurückkonvertieren in VARCHAR) die führenden Nullen entfernen.

Lösung

Microsoft SQL Server:

UPDATE tabelle SET material=
CASE WHEN isnumeric(material)=1 
        THEN convert(VARCHAR, convert(INTEGER, material))
        ELSE convert(VARCHAR, material)
END 

Microsoft Access:

   UPDATE articletexts SET material=
   IIF(IsNumeric(material), 
   REPLACE(LTRIM(REPLACE(material,'0',' '))
   ,' ','0'), material) 

Adobe Flex 3: Charaktere aus Flash Professional CS4 exportieren und einbinden

Aufgabenstellung

Es wird ein Grundgerüst für eine Flex-Anwendung erstellt, auf dessen Basis Animationen und Charaktere, die aus Flash CS4 exportiert worden, gesteuert werden können.

Intention

Da Adobe Flex als Entwicklungsumgebung für Programmierungen wesentlich mehr Features bietet als Flash (Context-Hilfe, Syntax-Highlighting, Design-Time-Prüfungen), wird versucht die Vorteile von Beiden Umgebungen zu nutzen und ein Flashspiel mit Flex, dessen Focus auf der Entwicklung mit Eclipse liegt, zu implementieren.

Ziel

Ziel ist das Auffinden von Bests Practices bei der Spieleentwicklung mit Flash/Flex.

Vorgehensweise 1

Erstellen von Animationen

Es werden 2 Loop-fähige Animationen erstellt, die nachher als Symbol konvertiert werden
Hier:
– Moving Landscape
– Character

Export aus Flash / Import in Flex

  • Flash schließen
  • Adobe Account anlegen
  • Flex Component Kit bei Adobe runterladen
  • Flex Component Kit mit Adobe Extension Installer installieren
  • Nur bei Problem mit Deutschen Versionen: Das in C:\User … … AppData … Adobe Flash CS4 … !!!DE!!! … Configuration-Verzeichnis in das auf der gleichen Ebene befindliche !!!EN!!! Verzeichnis kopieren
  • Flash neu starten
  • Die auf der Stage befindlichen Ebenen markieren
  • Menülieste: Modify -> Convert to Symbol
  • In Library (STRG+L) Symbol anklicken
  • Neues Menü: Command – Convert to Flex Component aufrufen
  • File->Publish aufrufen
  • In der Library auf dem neuen Flex Symbol -> Rechte Maustaste -> Convert to SWC (vorher auch unter Properties die Classnamen angeben)
  • In das Flex Projekt (lib-Verzeichnis) kopieren
  • Die Komponente steht in MXML zur Verfügung, wenn man den unter Properties angegebenen Classnamen aufruft

Versuch die Komponenten über Flex zu steuern

<?xml version="1.0" encoding="utf-8"?>
<mx:Application horizontalScrollPolicy="off" verticalScrollPolicy="off" 
          creationComplete="{onCreationComplete()}" 
         xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*" >
  <mx:Script>
  	<!&#91;CDATA&#91;
  		public function onCreationComplete():void
  		{
  			test3.scaleX=-1;
  		}
  	&#93;&#93;>
  </mx:Script>
 <local:landscape x="1400" y="600" height="600">
 </local:landscape>
 <local:MeinTest id="test3" height="300"  y="370" x="200" >
 </local:MeinTest>	
 <mx:ApplicationControlBar x="0" y="0" width="100%" height="50">
  <mx:Button click="{test3.gotoAndStop(0)}" label="Stop"/>
  <mx:Button click="{test3.gotoAndPlay(0)}" label="Start"/>
  <mx:Button click="{test3.scaleY*=-1;test3.scaleX*=-1}" label="Drehen"/>
 </mx:ApplicationControlBar>
</mx:Application>

Ergebnis

Problem

Die UIMovieClips lassen sich zwar rotieren, aber nicht per scaleX um die eigene Achse drehen.

Abhilfe

Wird noch gesucht

Adobe Flex 3: Composite Pattern für Charakter-Animation mit inverser Kinematik

Aufgabenstellung

Es wird eine Flex-Anwendung entwickelt, die das Grundgerüst für ein 360 Grad Flex-Spiel mit einer Schlange erstellt.

Ansatz

Unter der Verwendung des Composite-Patterns werden die Teile der Schlange zusammengesetzt. Die Teile interagieren über „inverse Kinematik“ miteinander, d.h. jedes Teil ist Autonom, wird aber von seinem Verbindungsteil gezogen.

Die Schlange verfügt über die Eigenschaften:
– gleichmäßig beschleunigte Bewegung (Up-Taste am Keyboard)
– gleichmäßig verzögerte Bewegung (Up-Taste loslassen)
– Rückimpuls (Kollision mit Button)
– Lenkung in der Beschleunigung (Left- und Right-Button)
– Jedes vordere Verbindungsstütz zur Schlange bestimmt die Position des hinteren (inverse Kinematik)

Der Code ist minimal, die Main-Datei besteht lediglich aus der Schlange selbst und der Angabe, welches UI-Objekt eine Barriere (hier „Der böse Button“) sein soll. Diese Barriere verfügt über die Eigenschaften des Back-Impulses bei einer Kollision in der Beschleunigung.

Main-Code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application backgroundColor="#ffffff" xmlns:mx="http://www.adobe.com/2006/mxml" 
                         layout="absolute" xmlns:snake="org.actionscript.snake.*">
  <snake:Snake barrier="{boeserButton}" height="100" width="100" snakelength="100" />
  <mx:Button x="10" y="256" id="boeserButton" width="400" label="Der böse Button" />
</mx:Application>

Lösung

In neuem Browser öffnen (bitte 1x anklicken und dann Pfeiltasten benutzen)

Code

Der Code wurde im Flex-Builder 3 entwickelt und ist als Flex 3-Projekt gezippt.
Adobe Flex 3 Projekt downloaden

C# und OleDBParameter: Reihenfolge von Parametern

Problem

(Ein kleiner Schmunzelartikel)… Da sitzt man seit Stunden vor einem normal aufgebaut SQL Statement mit einem OleDbCommand… es ist alles so wie bei einen SQLCommand…. und das Statement tut nichts… gar nichts…

Lösung

Die Reihenfolge von OleDBParametern ist NICHT assoziativ wie durch die Namensgebung vermutet… es spielt gar keine Rolle ob ein Statement mit einem ? oder einem @parametername versehen wird. Die Reihenfolge muss immer stimmen, wenn man mit

comm.Parameters.AddWithValue("parametername", variable) 

HTML 5 – Unterstützung des IE 9 Stand: 25. Februar 2011

Hier ein kurzer Post….

IE9 hängt dem HTML 5 Standard weit hinterher

Der Microsoft Internet Explorer 9 schneidet bei HTML5Test.com in seiner aktuellsten Beta-Version immer noch schlechter ab, als ein Firefox, welcher bereits 1 Jahr alt ist. Chrome hat auch kräftig zugelegt. Ich habe die IE9 Beta gerade (25. Februar 2011) frisch runtergeladen und erhalte folgendes niederschmetterndes Ergebnis:

Zum Vergleich ein Screenshot des Android Browsers auf dem Samsung Galaxy i9000 :

image

Wichtige Innovationen sollen nicht unterstützt werden

Da Microsoft eine ActiveX-Variante von Direct3D anbietet, besteht keine Intention für eine Implementierung der WebGL-API, die das darstellen von 3D-Objekten im Browser unterstützt. Sollte sich das auf weitere Releases auswirken ist WebGL eine Totgeburt, oder der Internet Explorer wird aussterben.

Es ist keine IndexedDB zur Speicherung von Offline-Inhalten geplant, Webworkers/Websockets sind nicht vorhanden.

SAP und JAVA: Zugriff auf Funktionsbausteine / BAPIs mit dem Java Connector

Aufgabenstellung

Es soll auf Daten aus dem SAP System zugegriffen werden, ohne die Datenbank direkt anzusprechen.

Ansatz

Durch die Verwendung des Java-Connectors (JCo) werden Funktionsbausteine / BAPIs als SAP Schnittstellen verwendet. Die Funktionsbausteine können über die SAP GUI mit dem BAPI-Explorer gesucht und mit der TA 37 getestet werden. Der nachfolgende Artikel beschäftigt sich mit dem Aufruf von einem Java-Server. Der JCo kann im Market Place von SAP kostenlos heruntergeladen werden.

Lösung

Remote Function Call (techn. RPC)

Ein Remote Function Call (RFC) ist die SAP-Implementierung von Remote Procedure Calls (RPC). Über einen RFC lassen sich Funktionsbausteine, bzw. BAPI’s aufrufen.

Ein RFC verwendet die Kommunikationsregeln des CPI-C-Protokolls, welches auf TCP/IP oder LU 6.2 basiert. LU 6.2 war dabei das Kommunikationsprotokoll von R/2-Mainframe-Systemen und wurde bei R/3 durch den einheitlichen TCP/IP-Standard ersetzt.

RFC’s nehmen ausschließlich Call-By-Value-Parameter entgegen, da die Übergabe von Zeigern und Speicheradressen hier keinen Sinn macht. In einem fremden System würde die Speicheradresse auf einen Speicher-Bereich zeigen, in dem keine oder Daten von anderen Anwendungen vorhanden sind.

Funktionsweise des Java Connectors (JCo)

Der Java Connector unterstützt den Aufruf von RFC’s, bzw. BAPIs aus einer externen Java-Umgebung (SAP-inbound-call), sowie den Aufruf externer JAVA-Funktionalitäten aus ABAP-Programmen heraus (SAP-outbound-call). Für die letztgenannte Variante existiert im Example-Verzeichnis des JCo ein Beispiel, in dem ein JCo-Server implementiert wird. Der JCo-Server muss dem SAP-System über die Transaktion SM59 bekanntgemacht werden.

Bei einem SAP-Inbound-Call ist die Vorgehensweise die folgende:

1.) Anmeldung der Java-Applikation am R/3-System

JCO.Client Conection = JCO.createClient(Mandant,
                                        Username,
                                        Password,
                                        Language,
                                        Hostname,
                                        Systemnummer);

Connection.connect();

2.) Herunterladen des Repository für den Funktionsbaustein

IRepository rep = JCO.createRepository("MyRepository", Connection);
IFunctionTemplate template = rep.getFunctionTemplate("BAPI_NAME");
JCO.Function funktion = new JCO.Function(template);

3.) Holen einer Referenz auf die Übergabeparameter

JCO.ParameterList import = funktion.getImportParameterList();
JCO.ParameterList table = funktion.getTableParameterList();

4.) Befüllen des Bausteins

5.) Funktionsbaustein ausführen

Connection.execute(funktion);

6.) Hole Referenz auf Rückgabeparameter

JCO.ParameterList export = funktion.getExportParameterList();
JCO.ParameterList table = funktion.getTableParameterList();

7.) Auslesen des Bausteins

Es werden synchrone (sRFC), asynchrone (aRFC) und transaktionale Aufrufe (tRFC, qRFC), sowie Connection-Pooling unterstützt (auf JAVA- wie auf ABAP-Seite).

SAP lobt zwar die Plattformunabhängigkeit des Connectors, jedoch stößt man bei einfachem Kopieren des Bytecodes auf Probleme, da hier eine plattformabhängige Bibliotheksdatei gekapselt wird, die bei höheren Releases nicht mehr funktioniert. Unter Windows wird die Datei librfc32.dll und unter Linux die Datei librfccm.so gekapselt.

Durch die Kapselung der Datei ist es ohne weiteres möglich, Konnektoren für nicht unterstützte Programmiersprachen zu implementieren.

Ein Tutorial der Zeitschrift „Der Entwickler“, welches Online zur Verfügung steht, zeigt durch Verwendung dieser Bibliothek, wie man Delphi an SAP-Systeme andocken kann. Der Artikel trägt den Namen „Delphi goes SAP“. Da es für Delphi keine Konnektoren wie den Java Connector gibt, ist die Kapselung dieser Datei notwendig.

Parameter von Funktionsbausteinen

Da die meisten SAP-Anwendungen im ABAP-Stack implementiert worden, greift man mit dem JAVA Connector hauptsächlich auf remotefähige Funktionsbausteine zu. Diesen werden entweder ausgefüllte Tabellen, oder Import-Parameter zur Verarbeitung übergeben. Als Ausgabe liefert ein Funktionsbaustein Fehler-Parameter, Export-Parameter, neue Tabellen oder auch die übergebenen Tabellen mit neuen Werten zurück. Hierfür ist es notwendig den syntaktischen Aufbau von JCO-Syntax zu kennen.

Import-Parameter

Import-Parameter kann man sich wie einfache Übergabeparametern aus bekannten Programmiersprachen vorstellen. Ein Import-Parameter entspricht einem Feld, was einen Datentyp beinhaltet (Char, Integer, String, Double…). Es kann keine Array’s, Listen oder Tabellen entgegennehmen.

SAP kennzeichnet hauseigene Funktionsbausteine mit einem vorangehenden I für „Import“. Mit der Transaktion SE16 ist es möglich sich die notwendigen Import-Parameter anzusehen.

Nicht alle Import-Parameter sind erforderlich, es gibt auch optionale Parameter. Nicht jeder Funktionsbaustein hat Import-Parameter.

Der nachstehende Code zeigt, wie mit Hilfe des JAVA Connectors der Funktionsbaustein „CFX_API_USER_GETDETAIL“, der die Detaildaten eines cFolders-Benutzers zurückgibt befüllt wird:

public String gibListeVonUsern()
{
  IRepository repository = JCO.createRepository("MYRepository", client);
  IFunctionTemplate ftemplate = repository
 .getFunctionTemplate("CFX_API_USER_GETDETAIL");
  Function func = ftemplate.getFunction();

  JCO.ParameterList input = func.getImportParameterList();
  input.setValue("KARPBJ01", "I_USER_ID");

  // Funktion aufrufen
  client.execute(func);
  (...)
}

Export-Parameter

Nachdem die Funktion ausgeführt wurde, kann über die Export-Parameter iteriert werden um die Rückgabewerte auszulesen. Dazu hat die Klasse ParameterList die Methode getFieldCount(), welche die Anzahl der Rückgabeparameter zurückliefert. Die Methode getString(index) ermöglich über den inkrementellen Index die Iteration mit einer Schleife. Dadurch lassen sich alle Parameter dynamisch auslesen.

Nachfolgend wird aus der aufgerufenden Funktion über die Export-Parameterliste iteriert und das Ergebnis an den String „informationen“ angehangen.


public String gibListeVonUsern()
{
  (...) //Hier war der Funktionsaufruf

  JCO.ParameterList output = func.getExportParameterList();

  for (int i = 0; i < output.getFieldCount(); i++)
  {
    informationen = informationen + output.getString(i) + "\n";
  }
  return informationen;
}

Changing-Parameter

Im Gegensatz zu Import- und Export-Parametern funktionieren Changing-Parameter in beide Richtungen (bidirektional). Der Aufruf ist dabei Call-By-Reference-ähnlich, da sich nach dem Ausführen des Funktionsbausteins mit dem Befehl client.execute(func); der Wert im Feld ändern kann. Das Befüllen und auslesen funktioniert dabei wie bei den Import- und Export-Parametern.

Table-Parameter

Table-Parameter sind bidirektional. Die Referenz auf eine Tabelle kann geholt werden, bevor die Funktion ausgeführt wurde. Hat man die Referenz auf die Tabelle, so lässt sich diese folgendermaßen befüllen:


  // Iteration über einen Vector
  for (int i = 0; i < vector.size(); i++)
  {
     // Neue Zeile an Tabelle anhängen und auf
     // neue Zeile wechseln
     table.appendRow();

     // schreibe in erste Spalte
     table.setValue((String)vector.get(i),0);

     // schreibe in zweite Spalte
     table.setValue((String)vector.get(i),1);
  }

Nachdem eine Funktion ausgeführt wurde, also nachdem Connection.execute(funktion); ausgeführt wurde, kann eine neue Tabelle zurückgeliefert werden, oder eine bereits befüllte Tabelle neue Werte beinhalten.

Um über eine Rückgabetabelle zu iterieren, gibt es die Funktion setRow(index). Das folgende Beispiel zeigt die Suche nach einem bestimmten String in der 3. Spalte und liefert das Feld „ID“ zurück:


  String rueckgabe = null;
  for (int i=0;i<outputtabelle.getNumRows();i++)
  {
    outputtabelle.setRow(i);

    if (outputtabelle.getString(2).equals(suche) )
    {
      rueckgabe = outputtabelle.getString("ID");
    }
  }

Wie ersichtlich wird, lässt sich die Spalte nicht nur anhand des inkrementellen Indexes ansprechen, sondern auch über den Spaltennamen.

In manchen Fällen ist es nötig eine eigene Tabelle zu erzeugen und diese an einen Funktionsbaustein zu übergeben. Zum Beispiel funktioniert die Zuweisung einer befüllten Ergebnistabelle an eine Übergabetabelle nicht, in diesem Fall muss man die Daten in einer Schleife einfach rauskopieren.

Eine eigene Tabellendefinition erzeugt man in diesem Fall so:


  JCO.MetaData smeta  = new JCO.MetaData("DIS");

  smeta.addInfo("DOKAR",  JCO.TYPE_STRING,  3,  0, 0);
  smeta.addInfo("DOKVR",  JCO.TYPE_STRING ,   2, 0, 0);
  smeta.addInfo("DOKTL",  JCO.TYPE_STRING ,   3, 0, 0);
  smeta.addInfo("DOKNR",  JCO.TYPE_STRING ,   3, 0, 0);

  JCO.Structure structure = new JCO.Structure(smeta); 
  JCO.Table table = new JCO.Table(structure);

Struktur-Parameter

Strukturen gehören zu den Tabellen-Typ-Parametern und sind Sonderfälle. Eine Struktur kann innerhalb einer Tabelle, in Import- oder Export-Parametern auftreten. Hierbei handelt es sich lediglich um eine weitere Aufteilung innerhalb eines einzigen Feldes.

Der folgende Code zeigt, wie eine Referenz auf eine Inputstruktur und auf einen normalen Import-Parameter geholt wird .


JCO.Structure struktur =
func.getImportParameterList().getStructure("SELECT_DOCUMENTDATA");
JCO.ParameterList inputdata = func.getImportParameterList();
struktur.setValue(art, "DOCUMENTTYPE");
inputdata.setValue("X", "GETCLASSIFICATION");
Output.execute(funktion);

Fortsetzung folgt …

by Björn Karpenstein