Donnerstag, 27. Mai 2010

COMA/Solaris: Auf das Coderverzeichnis zugreifen

ln -s "/mnt/cifs/$USER@webdev.leipzig.ufz.de:coder" coder

COMA/Solaris: Auf das Coderverzeichnis zugreifen

ln -s "/mnt/cifs/$USER@webdev.leipzig.ufz.de:coder" coder

Dienstag, 11. Mai 2010

BioScripter - Script Generator für Pipettierroboter v1

Im Rahmen seiner Doktorarbeit arbeitet Robert Schäwe, Wissenschaftler am UFZ, mit dem Pipettierroboter BioMek 2000.
Der Roboter muß in diesem Zusammenhang große Mengen von Probentöpfchen mit Bakterien verschiedenster Kulturen befüllen. Um ein möglichst genaues Versuchsergebnis zu erhalten, ist es erforderlich, die Proben in einem sehr kurzem Zeitraum zusammenzustellen.

Projektposter

Projektposter

Da die Standardsoftware des Roboters entsprechend optimierte Funktionen nicht bereithält, wurde Fachinformatiker-Azubi Andreas Menge mit der Erstellung eines neuen Programms beauftragt. Mit diesem werden nun die optimerten Pipettierschritte errechnet und an den Roboter gesandt.

Der BioMek beim Abarbeiten der optimierten Pipettierschritte.

Das Pipettierschema, aus dem hervorgeht in welchen Mengen welche Kulturen in die jeweiligen Probentöpfchen kommen, wird dabei als Excel-Arbeitsmappe bereitgestellt. Diese Datei wird vom BioScripter importiert und die Befüllungsmatrix durch einen Algorithmus umgewandelt, der sowohl die gewünschte Geschwindigkeit erzielt wie auch auch Kreuzkontamination verhindert.

Projektpräsentation

Projektpräsentation

Pressemitteilung in der Leipziger Volkszeitung

Pressemitteilung in der Leipziger Volkszeitung vom 21.05.2010

Aus Zeitgründen wurde das C#-Programm für diesen speziellen Versuch entwickelt und lässt momentan keine weiteren Anwendungen zu. Deshalb wird das Programm zur Zeit weiterentwickelt. Dabei wird vor allem Punkto Benutzerfreundlichkeit und Flexibilität einiges verbessert werden.

BioScripter - Script Generator für Pipettierroboter v1

Im Rahmen seiner Doktorarbeit arbeitet Robert Schäwe, Wissenschaftler am UFZ, mit dem Pipettierroboter BioMek 2000.
Der Roboter muß in diesem Zusammenhang große Mengen von Probentöpfchen mit Bakterien verschiedenster Kulturen befüllen. Um ein möglichst genaues Versuchsergebnis zu erhalten, ist es erforderlich, die Proben in einem sehr kurzem Zeitraum zusammenzustellen.

Projektposter

Projektposter

Da die Standardsoftware des Roboters entsprechend optimierte Funktionen nicht bereithält, wurde Fachinformatiker-Azubi Andreas Menge mit der Erstellung eines neuen Programms beauftragt. Mit diesem werden nun die optimerten Pipettierschritte errechnet und an den Roboter gesandt.

Der BioMek beim Abarbeiten der optimierten Pipettierschritte.

Das Pipettierschema, aus dem hervorgeht in welchen Mengen welche Kulturen in die jeweiligen Probentöpfchen kommen, wird dabei als Excel-Arbeitsmappe bereitgestellt. Diese Datei wird vom BioScripter importiert und die Befüllungsmatrix durch einen Algorithmus umgewandelt, der sowohl die gewünschte Geschwindigkeit erzielt wie auch auch Kreuzkontamination verhindert.

Projektpräsentation

Projektpräsentation

Pressemitteilung in der Leipziger Volkszeitung

Pressemitteilung in der Leipziger Volkszeitung vom 21.05.2010

Aus Zeitgründen wurde das C#-Programm für diesen speziellen Versuch entwickelt und lässt momentan keine weiteren Anwendungen zu. Deshalb wird das Programm zur Zeit weiterentwickelt. Dabei wird vor allem Punkto Benutzerfreundlichkeit und Flexibilität einiges verbessert werden.

Dienstag, 20. April 2010

SVG: Im <OBJECT>-Tag anklickbar machen (Teil 2)

Hier noch eine weitere Variante, welche praktikabler bei Funktionsaufrufen ist. Auf die Größenangabe über den DIV-Selektor wurde hier verzichtet, weiterhin wird als Parent-Element der <SPAN>-Tag verwendet, was ein horizontales Aneinanderreihen der Grafiken erleichtert.
Die hier beschriebene Methode (ohne style-Attribut) ist von der Struktur her, etwas sauberer.

Beispiel

http://www.ufz.de/

<span class="svglink" style="width: 167px; height: 77px;">
<a href="javascript:alert('Test')" style="width: 167px; height: 77px;"></a>
<object data="logo.svg" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>
</span>

Die CSS-Klasse svglink


.svglink {
position: relative;
}
span.svglink {
display: inline-block;
}
/* IE7-Hack, gleicht das Aussehen etwas an */
*+html .svglink {
padding: 0 0.25em 0.25em 0;
}
.svglink a, .svglink object {
position: absolute;
width: inherit;
height: inherit;
}
.svglink a {
/* Die (beiden!) Eigenschaften sind wichtig,
da im IE die SVG sonst nicht anklickbar ist. */
background-image: url(1x1transp.gif);
background-color: transparent;
z-index: 2;
}
.svglink object {
z-index: 1;
}

Der Unterschied zu der hier beschriebenen Methode, ist die Zuweisung von display: inline-block; bei der Verwendung des <SPAN>-Tags.
Es kann parallel mit dem <DIV>-Tag gearbeitet werden.

Download Beispielkomplettes Beispiel

SVG: Im <OBJECT>-Tag anklickbar machen (Teil 2)

Hier noch eine weitere Variante, welche praktikabler bei Funktionsaufrufen ist. Auf die Größenangabe über den DIV-Selektor wurde hier verzichtet, weiterhin wird als Parent-Element der <SPAN>-Tag verwendet, was ein horizontales Aneinanderreihen der Grafiken erleichtert.
Die hier beschriebene Methode (ohne style-Attribut) ist von der Struktur her, etwas sauberer.

Beispiel

http://www.ufz.de/

<span class="svglink" style="width: 167px; height: 77px;">
<a href="javascript:alert('Test')" style="width: 167px; height: 77px;"></a>
<object data="logo.svg" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>
</span>

Die CSS-Klasse svglink


.svglink {
position: relative;
}
span.svglink {
display: inline-block;
}
/* IE7-Hack, gleicht das Aussehen etwas an */
*+html .svglink {
padding: 0 0.25em 0.25em 0;
}
.svglink a, .svglink object {
position: absolute;
width: inherit;
height: inherit;
}
.svglink a {
/* Die (beiden!) Eigenschaften sind wichtig,
da im IE die SVG sonst nicht anklickbar ist. */
background-image: url(1x1transp.gif);
background-color: transparent;
z-index: 2;
}
.svglink object {
z-index: 1;
}

Der Unterschied zu der hier beschriebenen Methode, ist die Zuweisung von display: inline-block; bei der Verwendung des <SPAN>-Tags.
Es kann parallel mit dem <DIV>-Tag gearbeitet werden.

Download Beispielkomplettes Beispiel

Montag, 19. April 2010

Flash: Audio-Datei in Webseite einbetten

Nachfolgend beschreibe ich Schritt für Schritt das Erzeugen und Einbetten einer Audiodatei als Flash-Objekt in eine Webseite.

  1. Die Audiodatei am besten im WAV-Format z.B. mit einem Handy aufzeichnen (wenn möglich gleich als MP3 speichern).
  2. Liegt bereits eine MP3-Datei vor, kann dieser Punkt übersprungen werden. Jetzt sollte ein geeigneter MP3-Encoder gefunden werden, hier kann man z.B. den WAV to MP3 Converter benutzen (Herstellerseite).
    Die Bedienung des Tools ist einfach, die gewünschten Dateien über Add hinzufügen und dann Start klicken.
  3. Verringern Sie die Bit- und Samplerate (max.160kbs/44100Hz) wie im Screenshot dargestellt, sonst kann es später Probleme beim Import nach Flash geben.

Erforderliche Einstellungen im MP3-Encoder

  1. Ist die MP3-Datei erzeugt geht es im Adobe Flash, mit der im unten angehängten Download enthaltenen FLA-Datei, weiter. Öffnen Sie die FLA-Datei und wählen Datei->Importieren->In Bibliothek importieren....
    Anschließend sollte Ihre MP3 in der Bibliothek (Bibliothek evtl. mit STRG + L oder Fenster->Bibliothek öffnen) sichtbar sein. Im Kontextmenü (rechte Maustaste) der Datei wählen Sie Eigenschaften und nehmen die im Screenshot dargestellten Einstellungen vor (sind die gezeigten Einstellungen nicht sichtbar klicken Sie auf die Schaltfläche Erweitert).

var soundToLoad:Sound = new Sound();
startSound_btn.onRelease = function() {
var song = songName_txt.text;
soundToLoad.attachSound("mp3");
soundToLoad.start(0,1);
};

In der FLA-Datei integriertes Actionscript, welches die MP3-Datei beim Klick
auf das Symbol abspielt.

Aktivieren Sie die Checkbox Export für Actionscript
und tragen Sie unter Bezeichner "mp3" ein.
  1. Sollte die endgültige Soundqualität nicht ausreichen, können Sie im oben gezeigten Dialogfeld unter dem Dropdown Komprimierung->MP3 weitere Einstellungen vornehmen.
  2. Anschließend wird das Projekt mit den Standardeinstellungen über Datei->Veröffentlichen veröffentlicht, dabei sollte am Speicherort der FLA-Datei eine SWF- und eine HTML-Datei entstehen.
  3. Jetzt muss die SWF-Datei auf den Webserver hochgeladen werden. Am UFZ benutzt man dazu das Bild- und Filearchiv im administrativen Intranetbereich. Man lädt hier die SWF-Datei hoch und erhält eine ID (z.B. 123456).
  4. Jetzt muss man die hochgeladene Datei noch in der HTML-Datei referenzieren. Entweder die beim Veröffentlichen entstandene HTML-Datei verwenden oder den unten stehenden Quelltext (am UFZ wird für die Dateireferenz das Makro getfiler verwendet).

HTML-Quelltext zur Verwendung auf der eigenen Webseite

Achten Sie bitte darauf, dass die SWF-Datei zweimal referenziert werden muss, hier mit Hilfe des Makroaufrufs [§fgetfiler_123456§] (UFZ-Beispiel, ansonsten ohne das Makro z.B. http://www.foo.com/data/sample123456.swf).

Symbol anklicken um den Sound zu hören


<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="37" height="41" id="erste_sahne" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="[§fgetfiler_123456§]" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<embed src="[§fgetfiler_123456§]" quality="high" bgcolor="#ffffff" width="37" height="41" name="erste_sahne" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
Download Beispiel 3komplettes Beispiel

Flash: Audio-Datei in Webseite einbetten

Nachfolgend beschreibe ich Schritt für Schritt das Erzeugen und Einbetten einer Audiodatei als Flash-Objekt in eine Webseite.

  1. Die Audiodatei am besten im WAV-Format z.B. mit einem Handy aufzeichnen (wenn möglich gleich als MP3 speichern).
  2. Liegt bereits eine MP3-Datei vor, kann dieser Punkt übersprungen werden. Jetzt sollte ein geeigneter MP3-Encoder gefunden werden, hier kann man z.B. den WAV to MP3 Converter benutzen (Herstellerseite).
    Die Bedienung des Tools ist einfach, die gewünschten Dateien über Add hinzufügen und dann Start klicken.
  3. Verringern Sie die Bit- und Samplerate (max.160kbs/44100Hz) wie im Screenshot dargestellt, sonst kann es später Probleme beim Import nach Flash geben.

Erforderliche Einstellungen im MP3-Encoder

  1. Ist die MP3-Datei erzeugt geht es im Adobe Flash, mit der im unten angehängten Download enthaltenen FLA-Datei, weiter. Öffnen Sie die FLA-Datei und wählen Datei->Importieren->In Bibliothek importieren....
    Anschließend sollte Ihre MP3 in der Bibliothek (Bibliothek evtl. mit STRG + L oder Fenster->Bibliothek öffnen) sichtbar sein. Im Kontextmenü (rechte Maustaste) der Datei wählen Sie Eigenschaften und nehmen die im Screenshot dargestellten Einstellungen vor (sind die gezeigten Einstellungen nicht sichtbar klicken Sie auf die Schaltfläche Erweitert).

var soundToLoad:Sound = new Sound();
startSound_btn.onRelease = function() {
var song = songName_txt.text;
soundToLoad.attachSound("mp3");
soundToLoad.start(0,1);
};

In der FLA-Datei integriertes Actionscript, welches die MP3-Datei beim Klick
auf das Symbol abspielt.

Aktivieren Sie die Checkbox Export für Actionscript
und tragen Sie unter Bezeichner "mp3" ein.
  1. Sollte die endgültige Soundqualität nicht ausreichen, können Sie im oben gezeigten Dialogfeld unter dem Dropdown Komprimierung->MP3 weitere Einstellungen vornehmen.
  2. Anschließend wird das Projekt mit den Standardeinstellungen über Datei->Veröffentlichen veröffentlicht, dabei sollte am Speicherort der FLA-Datei eine SWF- und eine HTML-Datei entstehen.
  3. Jetzt muss die SWF-Datei auf den Webserver hochgeladen werden. Am UFZ benutzt man dazu das Bild- und Filearchiv im administrativen Intranetbereich. Man lädt hier die SWF-Datei hoch und erhält eine ID (z.B. 123456).
  4. Jetzt muss man die hochgeladene Datei noch in der HTML-Datei referenzieren. Entweder die beim Veröffentlichen entstandene HTML-Datei verwenden oder den unten stehenden Quelltext (am UFZ wird für die Dateireferenz das Makro getfiler verwendet).

HTML-Quelltext zur Verwendung auf der eigenen Webseite

Achten Sie bitte darauf, dass die SWF-Datei zweimal referenziert werden muss, hier mit Hilfe des Makroaufrufs [§fgetfiler_123456§] (UFZ-Beispiel, ansonsten ohne das Makro z.B. http://www.foo.com/data/sample123456.swf).

Symbol anklicken um den Sound zu hören


<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="37" height="41" id="erste_sahne" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="[§fgetfiler_123456§]" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<embed src="[§fgetfiler_123456§]" quality="high" bgcolor="#ffffff" width="37" height="41" name="erste_sahne" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
Download Beispiel 3komplettes Beispiel

Mittwoch, 14. April 2010

HTML/Javascript: Framegröße an Inhalte anpassen

Das folgende Beispiel kann genutzt werden, wenn man die Framegröße automatisch an wechselnde Inhaltgrößen anpassen möchte. Ein Anwendungsfall wären die UFZ-Adventskalender, welche sich als Popup öffnen und Kalender unterschiedlicher Größe zeigen. Frames sind hier deshalb eingesetzt weil sich das Menü zum Wechseln der Kalender in einem solchen befindet (siehe Screenshots).

Download komplettes Beispielkomplettes Beispiel

HTML/Javascript: Framegröße an Inhalte anpassen

Das folgende Beispiel kann genutzt werden, wenn man die Framegröße automatisch an wechselnde Inhaltgrößen anpassen möchte. Ein Anwendungsfall wären die UFZ-Adventskalender, welche sich als Popup öffnen und Kalender unterschiedlicher Größe zeigen. Frames sind hier deshalb eingesetzt weil sich das Menü zum Wechseln der Kalender in einem solchen befindet (siehe Screenshots).

Download komplettes Beispielkomplettes Beispiel

Dienstag, 13. April 2010

PHP: File Upload


<?php
$message = "";

if(isset($_FILES["file_name"]))
{
$upload_dir = "/www/data/";
$file_name = $_FILES['file_name']['name'];
$file_temp = $_FILES['file_name']['tmp_name'];

move_uploaded_file($file_temp,
$upload_dir.$file_name);

$message = "

$file_name
($file_size Byte) nach
$upload_dir hochgeladen!

";
}

$html = <<< HTML
<form action="{$_SERVER['PHP_SELF']}"
enctype="multipart/form-data"
method="post">
<input type="file" name="file_name" />
<input type="submit" value="Kopieren" />
</form>
HTML;

echo $html.$message;
?>

PHP: File Upload


<?php
$message = "";

if(isset($_FILES["file_name"]))
{
$upload_dir = "/www/data/";
$file_name = $_FILES['file_name']['name'];
$file_temp = $_FILES['file_name']['tmp_name'];

move_uploaded_file($file_temp,
$upload_dir.$file_name);

$message = "

$file_name
($file_size Byte) nach
$upload_dir hochgeladen!

";
}

$html = <<< HTML
<form action="{$_SERVER['PHP_SELF']}"
enctype="multipart/form-data"
method="post">
<input type="file" name="file_name" />
<input type="submit" value="Kopieren" />
</form>
HTML;

echo $html.$message;
?>

Freitag, 9. April 2010

SVG: Im <OBJECT>-Tag anklickbar machen (Teil 1)

Wer eine SVG wie im Post beschrieben einbettet, wird feststellen das man die Grafik nicht wie gewohnt verlinken kann (Beispiel 1). Auch die Verwendung eines onklick-Events führt nicht zum Erfolg (Beispiel 2).

Beispiel 1 (funktioniert nicht)

http://www.ufz.de/

<a href="javascript:alert('Test')">
<object data="logo.svg" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>
</a>

Beispiel 2 (funktioniert nicht)

http://www.ufz.de/

<object data="logo.svg" onlick="alert('Test')" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>

Abhilfe schafft hier das Schließen des Links (</a>) vor dem OBJECT-Tag und etwas CSS.

Beispiel 3 (funktioniert)


<div class="svglink" id="svg1">
<a href="javascript:alert('Test')"></a>
<object data="logo.svg" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>
</div>

Der Parameter wmode ist hier nicht optional, sonst ist die Grafik im IE nicht anklickbar.

Die CSS-Klasse svglink


.svglink {
position: relative;
}
.svglink a, .svglink object {
position: absolute;
width: inherit;
height: inherit;
}
.svglink a {
/* Die (beiden!) Eigenschaften sind wichtig,
da im IE die SVG sonst nicht anklickbar ist. */
background-image: url(1x1transp.gif);
background-color: transparent;
z-index: 2;
}
.svglink object {
z-index: 1;
}

Bei dem als Hintergrund verwendeten Bitmap, handelt es sich um eine 1 Pixel große GIF-Datei mit eingeschalteter Transparenz (sie ist auch Teil des unten angehängten Downloads).

Weitere CSS-Eigenschaften

Die Größe der Grafik sollte in em angegeben werden, um ein korrektes Skalieren zu ermöglichen. Deshalb ist hier ein weiterer DIV-Selektor notwendig, dieser korrigiert gleichzeitig das Fehlen der inherit CSS-Eigenschaft im IE6 und IE7.


/* IE7 kennt kein inherit,
daher der zusätzliche Selektor */
#svg1, #svg1 a {
width: 10.4375em; /* 167px / 16 = 10,4375em */
height: 4.8125em; /* 77px / 16 = 4,8125em */
}
Download Beispiel 3komplettes Beispiel

SVG: Im <OBJECT>-Tag anklickbar machen (Teil 1)

Wer eine SVG wie im Post beschrieben einbettet, wird feststellen das man die Grafik nicht wie gewohnt verlinken kann (Beispiel 1). Auch die Verwendung eines onklick-Events führt nicht zum Erfolg (Beispiel 2).

Beispiel 1 (funktioniert nicht)

http://www.ufz.de/

<a href="javascript:alert('Test')">
<object data="logo.svg" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>
</a>

Beispiel 2 (funktioniert nicht)

http://www.ufz.de/

<object data="logo.svg" onlick="alert('Test')" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>

Abhilfe schafft hier das Schließen des Links (</a>) vor dem OBJECT-Tag und etwas CSS.

Beispiel 3 (funktioniert)


<div class="svglink" id="svg1">
<a href="javascript:alert('Test')"></a>
<object data="logo.svg" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>
</div>

Der Parameter wmode ist hier nicht optional, sonst ist die Grafik im IE nicht anklickbar.

Die CSS-Klasse svglink


.svglink {
position: relative;
}
.svglink a, .svglink object {
position: absolute;
width: inherit;
height: inherit;
}
.svglink a {
/* Die (beiden!) Eigenschaften sind wichtig,
da im IE die SVG sonst nicht anklickbar ist. */
background-image: url(1x1transp.gif);
background-color: transparent;
z-index: 2;
}
.svglink object {
z-index: 1;
}

Bei dem als Hintergrund verwendeten Bitmap, handelt es sich um eine 1 Pixel große GIF-Datei mit eingeschalteter Transparenz (sie ist auch Teil des unten angehängten Downloads).

Weitere CSS-Eigenschaften

Die Größe der Grafik sollte in em angegeben werden, um ein korrektes Skalieren zu ermöglichen. Deshalb ist hier ein weiterer DIV-Selektor notwendig, dieser korrigiert gleichzeitig das Fehlen der inherit CSS-Eigenschaft im IE6 und IE7.


/* IE7 kennt kein inherit,
daher der zusätzliche Selektor */
#svg1, #svg1 a {
width: 10.4375em; /* 167px / 16 = 10,4375em */
height: 4.8125em; /* 77px / 16 = 4,8125em */
}
Download Beispiel 3komplettes Beispiel

Dienstag, 6. April 2010

SVG: Crossbrowser kompatibel & XHTML valide referenzieren

Alle Standardbrowser können mehr oder weniger mit SVG-Grafiken umgehen. Der IE, im Moment nur über das Adobe SVG-Plugin (Adobe SVG-Viewer 3.03). Ab Version 9 des IE ist hier Besserung in Sicht und damit haben SVG-Grafiken eine gute Chance, sich weiter zu verbreiten.

http://www.ufz.de/SVG-Grafik

<object data="logo.svg" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>

Der erste eingebettete param-Tag dient den IE's als Referenz auf die Datei. Der Internet Explorer kann hier keine Dateien per HTTP referenzieren!? Deshalb wird die Beispieldatei hier auch nicht angezeigt. Das sollte aber in der Praxis nicht weiter stören.
Der Parameter wmode ist optional, gleicht aber das Verhalten der SVG's im IE, an dass, der anderen Browser an.
Der eingebettete img-Tag wird benutzt wenn der Browser keine SVG anzeigen kann.

SVG: Crossbrowser kompatibel & XHTML valide referenzieren

Alle Standardbrowser können mehr oder weniger mit SVG-Grafiken umgehen. Der IE, im Moment nur über das Adobe SVG-Plugin (Adobe SVG-Viewer 3.03). Ab Version 9 des IE ist hier Besserung in Sicht und damit haben SVG-Grafiken eine gute Chance, sich weiter zu verbreiten.

http://www.ufz.de/SVG-Grafik

<object data="logo.svg" type="image/svg+xml" width="167" height="77">
<param name="src" value="logo.svg" />
<param name="wmode" value="transparent" />
<img src="logo.jpg" alt="http://www.ufz.de/" width="167" height="77" />
</object>

Der erste eingebettete param-Tag dient den IE's als Referenz auf die Datei. Der Internet Explorer kann hier keine Dateien per HTTP referenzieren!? Deshalb wird die Beispieldatei hier auch nicht angezeigt. Das sollte aber in der Praxis nicht weiter stören.
Der Parameter wmode ist optional, gleicht aber das Verhalten der SVG's im IE, an dass, der anderen Browser an.
Der eingebettete img-Tag wird benutzt wenn der Browser keine SVG anzeigen kann.

Excel/VBA: Letze Zeile mit Wert ermitteln

Der Methode Cells wird hier der zu untersuchende Bereich übergeben: Rows.Count = 65536 und die Spalte 1 = A

MsgBox(ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row)

Excel/VBA: Letze Zeile mit Wert ermitteln

Der Methode Cells wird hier der zu untersuchende Bereich übergeben: Rows.Count = 65536 und die Spalte 1 = A

MsgBox(ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row)

Freitag, 19. März 2010

Oracle: DROP TABLE OR SEQUENCE IF EXIST als Prozedur


CREATE OR REPLACE
PROCEDURE drop_object
(
ObjName IN VARCHAR2
) IS
counter NUMBER := 0;
to_drp VARCHAR2(200) := UPPER(ObjName);
drp_stmt VARCHAR2(200) := NULL;

BEGIN

SELECT COUNT(*)
INTO counter
FROM user_tables
WHERE table_name = to_drp;
IF counter = 1
THEN drp_stmt := 'Drop Table ' || to_drp;
EXECUTE IMMEDIATE drp_stmt;
END IF;

SELECT COUNT(*) INTO counter
FROM user_sequences
WHERE sequence_name = to_drp;
IF counter = 1 THEN
drp_stmt := 'DROP SEQUENCE ' || to_drp;
EXECUTE IMMEDIATE drp_stmt;
END IF;

END DROP_OBJECT;
/

Der Aufruf der Prozedur könnte z.B. so erfolgen:


CALL drop_object('t_test');
CREATE TABLE t_test
(
test_id NUMBER, uid_text VARCHAR2(80)
)

Oracle: DROP TABLE OR SEQUENCE IF EXIST als Prozedur


CREATE OR REPLACE
PROCEDURE drop_object
(
ObjName IN VARCHAR2
) IS
counter NUMBER := 0;
to_drp VARCHAR2(200) := UPPER(ObjName);
drp_stmt VARCHAR2(200) := NULL;

BEGIN

SELECT COUNT(*)
INTO counter
FROM user_tables
WHERE table_name = to_drp;
IF counter = 1
THEN drp_stmt := 'Drop Table ' || to_drp;
EXECUTE IMMEDIATE drp_stmt;
END IF;

SELECT COUNT(*) INTO counter
FROM user_sequences
WHERE sequence_name = to_drp;
IF counter = 1 THEN
drp_stmt := 'DROP SEQUENCE ' || to_drp;
EXECUTE IMMEDIATE drp_stmt;
END IF;

END DROP_OBJECT;
/

Der Aufruf der Prozedur könnte z.B. so erfolgen:


CALL drop_object('t_test');
CREATE TABLE t_test
(
test_id NUMBER, uid_text VARCHAR2(80)
)

Oracle: LDAP ID als Primärschlüssel


CALL drop_object('t_test');
CREATE TABLE t_test (test_id NUMBER, uid_text VARCHAR2(80));

CREATE OR REPLACE TRIGGER insert_lid
BEFORE INSERT ON t_test FOR EACH ROW

DECLARE
l_ldap_host VARCHAR2(256) := 'hera.leipzig.ufz.de';
l_ldap_port VARCHAR2(256) := '389';
l_ldap_base VARCHAR2(256) := 'dc=ufz,dc=de';
l_retval PLS_INTEGER;
l_session DBMS_LDAP.session;
l_attrs DBMS_LDAP.string_collection;
l_message DBMS_LDAP.message;
l_entry DBMS_LDAP.message;
l_vals DBMS_LDAP.string_collection;

BEGIN
l_session := DBMS_LDAP.init
(
hostname => l_ldap_host,
portnum => l_ldap_port
);

l_retval := DBMS_LDAP.simple_bind_s
(
ld => l_session,
dn => NULL,
passwd => NULL
);

l_attrs(0) := 'uidNumber';
l_retval := DBMS_LDAP.search_s
(
ld => l_session,
base => l_ldap_base,
scope => DBMS_LDAP.SCOPE_SUBTREE,
filter => '(&
(nsrole=*roleself*)
(objectClass=ufzperson)
(uid=' || :new.uid_text || ')
)',
attrs => l_attrs,
attronly => 0,
res => l_message
);

IF DBMS_LDAP.count_entries
(
ld => l_session,
msg => l_message
) = 1
THEN
l_entry := DBMS_LDAP.first_entry
(
ld => l_session,
msg => l_message
);

l_vals := DBMS_LDAP.get_values
(
ld => l_session,
ldapentry => l_entry,
attr => l_attrs(0)
);
END IF;

DBMS_OUTPUT.PUT_LINE
(
l_attrs(0) || ' = ' || l_vals(0)
);

l_retval := DBMS_LDAP.unbind_s
(
ld => l_session
);

:new.test_id := l_vals(0);

END;
/

Der Trigger könnte z.B. so ausgelöst werden:


INSERT INTO t_test (uid_text)
VALUES ('dutzend');

Oracle: LDAP ID als Primärschlüssel


CALL drop_object('t_test');
CREATE TABLE t_test (test_id NUMBER, uid_text VARCHAR2(80));

CREATE OR REPLACE TRIGGER insert_lid
BEFORE INSERT ON t_test FOR EACH ROW

DECLARE
l_ldap_host VARCHAR2(256) := 'hera.leipzig.ufz.de';
l_ldap_port VARCHAR2(256) := '389';
l_ldap_base VARCHAR2(256) := 'dc=ufz,dc=de';
l_retval PLS_INTEGER;
l_session DBMS_LDAP.session;
l_attrs DBMS_LDAP.string_collection;
l_message DBMS_LDAP.message;
l_entry DBMS_LDAP.message;
l_vals DBMS_LDAP.string_collection;

BEGIN
l_session := DBMS_LDAP.init
(
hostname => l_ldap_host,
portnum => l_ldap_port
);

l_retval := DBMS_LDAP.simple_bind_s
(
ld => l_session,
dn => NULL,
passwd => NULL
);

l_attrs(0) := 'uidNumber';
l_retval := DBMS_LDAP.search_s
(
ld => l_session,
base => l_ldap_base,
scope => DBMS_LDAP.SCOPE_SUBTREE,
filter => '(&
(nsrole=*roleself*)
(objectClass=ufzperson)
(uid=' || :new.uid_text || ')
)',
attrs => l_attrs,
attronly => 0,
res => l_message
);

IF DBMS_LDAP.count_entries
(
ld => l_session,
msg => l_message
) = 1
THEN
l_entry := DBMS_LDAP.first_entry
(
ld => l_session,
msg => l_message
);

l_vals := DBMS_LDAP.get_values
(
ld => l_session,
ldapentry => l_entry,
attr => l_attrs(0)
);
END IF;

DBMS_OUTPUT.PUT_LINE
(
l_attrs(0) || ' = ' || l_vals(0)
);

l_retval := DBMS_LDAP.unbind_s
(
ld => l_session
);

:new.test_id := l_vals(0);

END;
/

Der Trigger könnte z.B. so ausgelöst werden:


INSERT INTO t_test (uid_text)
VALUES ('dutzend');

Oracle: Per Trigger Website in CLOB einlesen

Die Tabelle für das Beispiel


CREATE TABLE t_pages
(
pages_id NUMBER,
url VARCHAR2(80),
page CLOB
);

-- Sequenz für das Increment der ID
CREATE SEQUENCE t_pages_autoinc_seq
START WITH 1
INCREMENT BY 1
NOCACHE
NOMAXVALUE;

-- Trigger zum Aufruf der Sequenz
CREATE OR REPLACE TRIGGER t_pages_autoinc_trigger
BEFORE INSERT ON t_pages
FOR EACH ROW
BEGIN
SELECT t_pages_autoinc_seq.NEXTVAL INTO :NEW.pages_id FROM DUAL;
END;
/

Der Trigger löst folgendes aus:
Wird ein Datensatz mit einer gültigen URL eingefügt, wird die Seite aufgerufen und der HTML-Code der Seite in den CLOB geschrieben.


CREATE OR REPLACE TRIGGER insert_page
BEFORE INSERT ON t_pages
FOR EACH ROW

DECLARE
req UTL_HTTP.req;
resp UTL_HTTP.resp;
page CLOB;

BEGIN
-- Verbindung aufbauen
req := UTL_HTTP.begin_request(:new.url);
-- Als Mozilla ausgeben
UTL_HTTP.set_header(req, 'User-Agent', 'Mozilla/4.0');

resp := UTL_HTTP.get_response(req);
UTL_HTTP.read_text(resp, page, 50000);
UTL_HTTP.end_response(resp);
:new.page := page;

EXCEPTION
WHEN
UTL_HTTP.end_of_body
THEN
UTL_HTTP.end_response(resp);
END;
/

Beispiel zum Aufrufen des Ganzen


INSERT INTO t_pages (url)
VALUES ('http://www.ufz.de/');

Oracle: Per Trigger Website in CLOB einlesen

Die Tabelle für das Beispiel


CREATE TABLE t_pages
(
pages_id NUMBER,
url VARCHAR2(80),
page CLOB
);

-- Sequenz für das Increment der ID
CREATE SEQUENCE t_pages_autoinc_seq
START WITH 1
INCREMENT BY 1
NOCACHE
NOMAXVALUE;

-- Trigger zum Aufruf der Sequenz
CREATE OR REPLACE TRIGGER t_pages_autoinc_trigger
BEFORE INSERT ON t_pages
FOR EACH ROW
BEGIN
SELECT t_pages_autoinc_seq.NEXTVAL INTO :NEW.pages_id FROM DUAL;
END;
/

Der Trigger löst folgendes aus:
Wird ein Datensatz mit einer gültigen URL eingefügt, wird die Seite aufgerufen und der HTML-Code der Seite in den CLOB geschrieben.


CREATE OR REPLACE TRIGGER insert_page
BEFORE INSERT ON t_pages
FOR EACH ROW

DECLARE
req UTL_HTTP.req;
resp UTL_HTTP.resp;
page CLOB;

BEGIN
-- Verbindung aufbauen
req := UTL_HTTP.begin_request(:new.url);
-- Als Mozilla ausgeben
UTL_HTTP.set_header(req, 'User-Agent', 'Mozilla/4.0');

resp := UTL_HTTP.get_response(req);
UTL_HTTP.read_text(resp, page, 50000);
UTL_HTTP.end_response(resp);
:new.page := page;

EXCEPTION
WHEN
UTL_HTTP.end_of_body
THEN
UTL_HTTP.end_response(resp);
END;
/

Beispiel zum Aufrufen des Ganzen


INSERT INTO t_pages (url)
VALUES ('http://www.ufz.de/');

Oracle: LDAP Connection mi dem DBMS_LDAP Package

Im folgenden wird das DBMS_LDAP-Package genutzt um auf einen LDAP-Server anonym zuzugreifen und den Wert eines bestimmten Attributes zu lesen.
Konkret ist das hier die LDAP-ID (uidNumber) einer bestimmten Person (ufzperson).
Die ID der Person soll später als Primärschlüssel in einer Oracle-Tabelle genutzt werden.


DECLARE
l_ldap_host VARCHAR2(256) := 'hera.leipzig.ufz.de';
l_ldap_port VARCHAR2(256) := '389'; -- varchar?
l_ldap_base VARCHAR2(256) := 'dc=ufz,dc=de';

l_retval PLS_INTEGER;
l_session DBMS_LDAP.session;
l_attrs DBMS_LDAP.string_collection;
l_message DBMS_LDAP.message;
l_entry DBMS_LDAP.message;
l_vals DBMS_LDAP.string_collection;

BEGIN
l_session := DBMS_LDAP.init
(
hostname => l_ldap_host,
portnum => l_ldap_port
);

-- anonym anmelden
l_retval := DBMS_LDAP.simple_bind_s
(
ld => l_session,
dn => NULL,
passwd => NULL
);

-- Attribut welches gesucht wird
l_attrs(0) := 'uidNumber';

-- Suche ausführen
l_retval := DBMS_LDAP.search_s
(
ld => l_session,
base => l_ldap_base,
scope => DBMS_LDAP.SCOPE_SUBTREE,
filter => '(&(nsrole=*roleself*)(objectClass=ufzperson)(uid=dutzend))',
attrs => l_attrs,
attronly => 0,
res => l_message);

-- Wenn genau ein Eintrag gefunden wurde
IF DBMS_LDAP.count_entries(ld => l_session, msg => l_message) = 1
THEN
-- ersten Eintrag festlegen
l_entry := DBMS_LDAP.first_entry
(
ld => l_session,
msg => l_message
);

-- Wert des Eintrages holen
l_vals := DBMS_LDAP.get_values
(
ld => l_session,
ldapentry => l_entry,
attr => l_attrs(0)
);
END IF;

-- Attribut und Wert ausgeben
DBMS_OUTPUT.PUT_LINE(l_attrs(0) || ' = ' || l_vals(0));

-- Verbindung beenden
l_retval := DBMS_LDAP.unbind_s(ld => l_session);
END;
/

Oracle: LDAP Connection mi dem DBMS_LDAP Package

Im folgenden wird das DBMS_LDAP-Package genutzt um auf einen LDAP-Server anonym zuzugreifen und den Wert eines bestimmten Attributes zu lesen.
Konkret ist das hier die LDAP-ID (uidNumber) einer bestimmten Person (ufzperson).
Die ID der Person soll später als Primärschlüssel in einer Oracle-Tabelle genutzt werden.


DECLARE
l_ldap_host VARCHAR2(256) := 'hera.leipzig.ufz.de';
l_ldap_port VARCHAR2(256) := '389'; -- varchar?
l_ldap_base VARCHAR2(256) := 'dc=ufz,dc=de';

l_retval PLS_INTEGER;
l_session DBMS_LDAP.session;
l_attrs DBMS_LDAP.string_collection;
l_message DBMS_LDAP.message;
l_entry DBMS_LDAP.message;
l_vals DBMS_LDAP.string_collection;

BEGIN
l_session := DBMS_LDAP.init
(
hostname => l_ldap_host,
portnum => l_ldap_port
);

-- anonym anmelden
l_retval := DBMS_LDAP.simple_bind_s
(
ld => l_session,
dn => NULL,
passwd => NULL
);

-- Attribut welches gesucht wird
l_attrs(0) := 'uidNumber';

-- Suche ausführen
l_retval := DBMS_LDAP.search_s
(
ld => l_session,
base => l_ldap_base,
scope => DBMS_LDAP.SCOPE_SUBTREE,
filter => '(&(nsrole=*roleself*)(objectClass=ufzperson)(uid=dutzend))',
attrs => l_attrs,
attronly => 0,
res => l_message);

-- Wenn genau ein Eintrag gefunden wurde
IF DBMS_LDAP.count_entries(ld => l_session, msg => l_message) = 1
THEN
-- ersten Eintrag festlegen
l_entry := DBMS_LDAP.first_entry
(
ld => l_session,
msg => l_message
);

-- Wert des Eintrages holen
l_vals := DBMS_LDAP.get_values
(
ld => l_session,
ldapentry => l_entry,
attr => l_attrs(0)
);
END IF;

-- Attribut und Wert ausgeben
DBMS_OUTPUT.PUT_LINE(l_attrs(0) || ' = ' || l_vals(0));

-- Verbindung beenden
l_retval := DBMS_LDAP.unbind_s(ld => l_session);
END;
/

Dienstag, 16. März 2010

Linux/Solaris: Dateiname in Textdateien einfügen

Um den jeweiligen Dateinamen in die 2. Zeile aller Textdateien einzufügen, die in einem Verzeichnis liegen, kann man folgende Befehlszeile im verwenden:

for i in *.*; do sed -i "2i\\$i" $i; done

Linux/Solaris: Dateiname in Textdateien einfügen

Um den jeweiligen Dateinamen in die 2. Zeile aller Textdateien einzufügen, die in einem Verzeichnis liegen, kann man folgende Befehlszeile im verwenden:

for i in *.*; do sed -i "2i\\$i" $i; done

Donnerstag, 11. März 2010

Linux/Solaris: Text in Dateien einfügen

  1. Terminal öffnen
  2. in den Ordner mit den Dateien wechseln (cd)
  3. sed -i "1i\Text in Zeile 1" *.mop
  4. sed -i "2i\Text in Zeile 2" *.mop

Linux/Solaris: Text in Dateien einfügen

  1. Terminal öffnen
  2. in den Ordner mit den Dateien wechseln (cd)
  3. sed -i "1i\Text in Zeile 1" *.mop
  4. sed -i "2i\Text in Zeile 2" *.mop

Windows 7: Test auf Unterstützung des TRIM-Befehls

fsutil behavior query disabledeletenotify

Die Meldung DisableDeleteNotify = 0 bedeutet in diesem Fall die Aktierung von Trim, eine DisableDeleteNotify = 1 würde seine Deaktivierung signalisieren.

Windows 7: Test auf Unterstützung des TRIM-Befehls

fsutil behavior query disabledeletenotify

Die Meldung DisableDeleteNotify = 0 bedeutet in diesem Fall die Aktierung von Trim, eine DisableDeleteNotify = 1 würde seine Deaktivierung signalisieren.

Dienstag, 9. März 2010

COMA: Linkicons und Glossarlinks setzen

Um z.B. in AJAX-Responses nachträglich die Glossarlinks und Linkicons zu setzen, kann man nachfolgende COMA-Funktion nutzen:

$html = "HTML mit Glossarbegriffen und Hyperlinks";
$root_pid = 28;
$html = linkicon_glossar_parser($html, $root_pid);
Der Parameter $root_pid entscheidet über das Setzen der Glossarlinks (Knoten 1 JA, Knoten 9 NEIN ?).

Zu ersetzende Linkicons müssen in einem DIV mit der ID content stehen (nicht valide da ID dann doppelt)!

COMA: Linkicons und Glossarlinks setzen

Um z.B. in AJAX-Responses nachträglich die Glossarlinks und Linkicons zu setzen, kann man nachfolgende COMA-Funktion nutzen:

$html = "HTML mit Glossarbegriffen und Hyperlinks";
$root_pid = 28;
$html = linkicon_glossar_parser($html, $root_pid);
Der Parameter $root_pid entscheidet über das Setzen der Glossarlinks (Knoten 1 JA, Knoten 9 NEIN ?).

Zu ersetzende Linkicons müssen in einem DIV mit der ID content stehen (nicht valide da ID dann doppelt)!

COMA: Makroparser aufrufen

Um z.B. Makros in AJAX-Responses zu parsen, kann man nachfolgende COMA-Funktion nutzen:

$html = "HTML mit einem Makro (§fgetpic_9908§)";
$html = ersetze_funktionstemplates
(
$conn, $sprache, $code, $html,
$baum, $adm, $su, $pub
);

COMA: Makroparser aufrufen

Um z.B. Makros in AJAX-Responses zu parsen, kann man nachfolgende COMA-Funktion nutzen:

$html = "HTML mit einem Makro (§fgetpic_9908§)";
$html = ersetze_funktionstemplates
(
$conn, $sprache, $code, $html,
$baum, $adm, $su, $pub
);

Montag, 8. März 2010

USB Stick ohne Floppy bootfähig machen

Man braucht für diese Methode eigentlich eine startfähige Diskette im Laufwerk,als Ersatz kann man Virtual Floppy Drive verwenden.
  1. ZIP-Datei an beliebiger Stelle entpacken
  2. VFDWIN.EXE als Administrator starten
  3. unter Driver auf Start klicken
  4. bei Drive 0 oder Drive 1 mittels Change den Laufwerksbuchstaben auf A setzen
  5. Open und dann Create klicken (Image File bleibt leer)
  6. im Explorer den Arbeitsplatz öffnen
  7. Rechtsklick auf 3½-Diskette A - Formatieren - MS-DOS Startdiskette erstellen

Systemdateien auf den Stick übertragen

  1. HP USB Disk Storage Format Tool installieren
  2. USB Stick einstecken
  3. HP Tool starten
  4. Bei Device den Stick wählen
  5. Häkchen bei Create DOS Startup Diskusing DOS System Files located at A:\ machen

USB Stick ohne Floppy bootfähig machen

Man braucht für diese Methode eigentlich eine startfähige Diskette im Laufwerk,als Ersatz kann man Virtual Floppy Drive verwenden.
  1. ZIP-Datei an beliebiger Stelle entpacken
  2. VFDWIN.EXE als Administrator starten
  3. unter Driver auf Start klicken
  4. bei Drive 0 oder Drive 1 mittels Change den Laufwerksbuchstaben auf A setzen
  5. Open und dann Create klicken (Image File bleibt leer)
  6. im Explorer den Arbeitsplatz öffnen
  7. Rechtsklick auf 3½-Diskette A - Formatieren - MS-DOS Startdiskette erstellen

Systemdateien auf den Stick übertragen

  1. HP USB Disk Storage Format Tool installieren
  2. USB Stick einstecken
  3. HP Tool starten
  4. Bei Device den Stick wählen
  5. Häkchen bei Create DOS Startup Diskusing DOS System Files located at A:\ machen

Mittwoch, 3. März 2010

COMA: Cron-Job einrichten

Als erstes erstellt man das Makro, welches per Cron aufgerufen werden soll.
Danach sucht man sich in der Datenbank die Tabelle W_CJ.
In die Spalte CJ_FKT trägt man den Namen des Makros ein.
Der Eintrag in die Spalte CJ_EXE besteht aus 4 Ziffern, die ersten beiden geben die volle Stunde an, in der das Makro gestartet wird (00 - 23).
Die beiden letzten stehen für den Tag im Monat an dem man das Makro ausführen möchte (01 - 31), 00 steht dabei für täglich.
In der Spalte CJ_LAST_EXE wird das Datum gesetzt an dem der Job zum letzten Mal ausgeführt wurde.

COMA: Cron-Job einrichten

Als erstes erstellt man das Makro, welches per Cron aufgerufen werden soll.
Danach sucht man sich in der Datenbank die Tabelle W_CJ.
In die Spalte CJ_FKT trägt man den Namen des Makros ein.
Der Eintrag in die Spalte CJ_EXE besteht aus 4 Ziffern, die ersten beiden geben die volle Stunde an, in der das Makro gestartet wird (00 - 23).
Die beiden letzten stehen für den Tag im Monat an dem man das Makro ausführen möchte (01 - 31), 00 steht dabei für täglich.
In der Spalte CJ_LAST_EXE wird das Datum gesetzt an dem der Job zum letzten Mal ausgeführt wurde.

Sonntag, 28. Februar 2010

Oracle: Autoincrement Workarounds

Da ORACLE den z.B. aus MySQL bekannten Datentyp auto_increment nicht kennt, nachfolgend zwei Möglichkeiten das auch in Oracle zu ermöglichen.

Tabelle für die Beispiele


create table teach_clients
(
id_clients number not null,
vorname varchar2(255),
zuname varchar2(255) not null,
geburtsdatum date,
constraint teach_clients_pk primary key
(
id_clients
)
enable
)

Unterabfrage mit Aggregatfunktion


insert into teach_clients
values
(
(
select
case
when max(id_clients) >= 1
then to_char(max(id_clients) + 1)
else to_char(1)
end
from teach_clients
),
'René',
'Tuchscherer',
'10.02.1963'
)

Trigger und Sequenz

Man erzeugt zwei zusätzliche Datenbankobjekte, eine Sequence und einen Trigger. Die Sequenz erzeugt die einzusetzenden Werte, der before-insert Trigger sorgt dafür, dass der neue Wert als erstes in der neuen Zeile landet.

-- die Sequenz erzeugen
create sequence id_clients_seq
start with 1
increment by 1
nomaxvalue;

-- den Trigger erzeugen
create trigger id_clients_trigger
before insert on teach_clients
for each row
begin
select id_clients_seq.nextval
into :new.id_client
from dual;
end;
Man kann statt start with 1 auch eine andere Zahl einsetzen, mit der begonnen werden soll.Das increment by 1 kann man eigentlich weglassen, weil es die Default-Einstellung ist.Der Parameter nomaxvalue sagt der Sequence, das sie für immer und ewig zu inkrementieren hat und nicht an irgendeinem Wert ein Reset machen soll.

Es kann übrigens durchaus sein, dass Zahlen "übersprungen" werden, weil sie von Oracle im Cache gehalten werden, um die Eindeutigkeit zu sichern. Wenn man also lückenlos aufsteigende Nummern haben muss, wäre dieser Ansatz nicht ausreichend.

Oracle: Autoincrement Workarounds

Da ORACLE den z.B. aus MySQL bekannten Datentyp auto_increment nicht kennt, nachfolgend zwei Möglichkeiten das auch in Oracle zu ermöglichen.

Tabelle für die Beispiele


create table teach_clients
(
id_clients number not null,
vorname varchar2(255),
zuname varchar2(255) not null,
geburtsdatum date,
constraint teach_clients_pk primary key
(
id_clients
)
enable
)

Unterabfrage mit Aggregatfunktion


insert into teach_clients
values
(
(
select
case
when max(id_clients) >= 1
then to_char(max(id_clients) + 1)
else to_char(1)
end
from teach_clients
),
'René',
'Tuchscherer',
'10.02.1963'
)

Trigger und Sequenz

Man erzeugt zwei zusätzliche Datenbankobjekte, eine Sequence und einen Trigger. Die Sequenz erzeugt die einzusetzenden Werte, der before-insert Trigger sorgt dafür, dass der neue Wert als erstes in der neuen Zeile landet.

-- die Sequenz erzeugen
create sequence id_clients_seq
start with 1
increment by 1
nomaxvalue;

-- den Trigger erzeugen
create trigger id_clients_trigger
before insert on teach_clients
for each row
begin
select id_clients_seq.nextval
into :new.id_client
from dual;
end;
Man kann statt start with 1 auch eine andere Zahl einsetzen, mit der begonnen werden soll.Das increment by 1 kann man eigentlich weglassen, weil es die Default-Einstellung ist.Der Parameter nomaxvalue sagt der Sequence, das sie für immer und ewig zu inkrementieren hat und nicht an irgendeinem Wert ein Reset machen soll.

Es kann übrigens durchaus sein, dass Zahlen "übersprungen" werden, weil sie von Oracle im Cache gehalten werden, um die Eindeutigkeit zu sichern. Wenn man also lückenlos aufsteigende Nummern haben muss, wäre dieser Ansatz nicht ausreichend.

Mittwoch, 20. Januar 2010

COMA: Angemeldeten User ermitteln


SELECT a.lid, b.login_name FROM web.wsess a, web.wlogin b WHERE sid = $sess_id AND a.lid = b.lid

COMA: Angemeldeten User ermitteln


SELECT a.lid, b.login_name FROM web.wsess a, web.wlogin b WHERE sid = $sess_id AND a.lid = b.lid

Oracle: Password ändern


ALTER USER name IDENTIFIED BY "password";

Oracle: Password ändern


ALTER USER name IDENTIFIED BY "password";

COMA: Bild dynamisch erzeugen

Hier als Makro umgesetzt, welches so aufgerufen wird:
[§fcreatePic§]


function createPic() {

if(isset($_REQUEST['getpic']) &&
Header("Content-type: image/jpeg");
$width = "300";
$height = "50";
// neues Bild erzeugen
$image = ImageCreateTrueColor($width, $height);
// Farben definieren
$col1 = ImageColorAllocate($image, 255, 255, 200);
$col2 = ImageColorAllocate($image, 0, 0, 0);
// Hintergrund mit Farbe füllen
ImageFill($image, 0, 0, $col1);
// Text dazu
ImageString ($image, 5, 20, 20,
"Coded bei FIAE", $col2);
// Grafik ausgeben
ImageJPEG($image);
// Speicher wieder frei geben
ImageDestroy($image);
}
else {
return "<img src=\"{$_SERVER["REQUEST_URI"]}&getpic\">";
}
}

COMA: Bild dynamisch erzeugen

Hier als Makro umgesetzt, welches so aufgerufen wird:
[§fcreatePic§]


function createPic() {

if(isset($_REQUEST['getpic']) &&
Header("Content-type: image/jpeg");
$width = "300";
$height = "50";
// neues Bild erzeugen
$image = ImageCreateTrueColor($width, $height);
// Farben definieren
$col1 = ImageColorAllocate($image, 255, 255, 200);
$col2 = ImageColorAllocate($image, 0, 0, 0);
// Hintergrund mit Farbe füllen
ImageFill($image, 0, 0, $col1);
// Text dazu
ImageString ($image, 5, 20, 20,
"Coded bei FIAE", $col2);
// Grafik ausgeben
ImageJPEG($image);
// Speicher wieder frei geben
ImageDestroy($image);
}
else {
return "<img src=\"{$_SERVER["REQUEST_URI"]}&getpic\">";
}
}

Dienstag, 19. Januar 2010

COMA: Oracle-Blob als Image-Stream

Hier als Makro umgesetzt, welches z.B. so aufgerufen wird:
[§fpicStream_13404§]
Als Parameter wird die gewünschte Bild-ID übergeben.


function picStream($conn, $param) {

if(isset($_REQUEST['getpic']) &&
is_numeric($param)) {

$sql = "select pics_blob from web.wpics
where pics_id=$param";
$stmt = OCIparse($conn, $sql) ;
OCIExecute($stmt,OCI_DEFAULT) ;
$check = OCIFetchInto($stmt, $row, OCI_ASSOC);
if($check == 1)
echo $row["PICS_BLOB"]->load();
}
else {
return "<img src=\"{$_SERVER["REQUEST_URI"]}&getpic\">";
}
}

COMA: Oracle-Blob als Image-Stream

Hier als Makro umgesetzt, welches z.B. so aufgerufen wird:
[§fpicStream_13404§]
Als Parameter wird die gewünschte Bild-ID übergeben.


function picStream($conn, $param) {

if(isset($_REQUEST['getpic']) &&
is_numeric($param)) {

$sql = "select pics_blob from web.wpics
where pics_id=$param";
$stmt = OCIparse($conn, $sql) ;
OCIExecute($stmt,OCI_DEFAULT) ;
$check = OCIFetchInto($stmt, $row, OCI_ASSOC);
if($check == 1)
echo $row["PICS_BLOB"]->load();
}
else {
return "<img src=\"{$_SERVER["REQUEST_URI"]}&getpic\">";
}
}

Donnerstag, 14. Januar 2010

COMA: LDAP per PHP durchsuchen


function search_user_ldap($string) {

$filter =
"(&
// aktiviert, deaktiviert, alle
(nsrole=*roleself*)
(objectclass=ufzperson)
// Attribut nach dem wir suchen (sn=Surname)
(sn=".$string."*)
)";
// Attribute die geliefert werden sollen
$attr = array("sn");
// Menge der Suchergebnisse (0=unbegrenzt)
$count = 0;
// Ergebnisarray
$search = array();

if(cldap_Search("", &$search, $filter, $attr, $count)) {

$search = cldap_DeleteCount($search, 1);

foreach($search as $val) {
$ret[] = $val[$attr[0]][0];
}
}
return $ret;
}

COMA: LDAP per PHP durchsuchen


function search_user_ldap($string) {

$filter =
"(&
// aktiviert, deaktiviert, alle
(nsrole=*roleself*)
(objectclass=ufzperson)
// Attribut nach dem wir suchen (sn=Surname)
(sn=".$string."*)
)";
// Attribute die geliefert werden sollen
$attr = array("sn");
// Menge der Suchergebnisse (0=unbegrenzt)
$count = 0;
// Ergebnisarray
$search = array();

if(cldap_Search("", &$search, $filter, $attr, $count)) {

$search = cldap_DeleteCount($search, 1);

foreach($search as $val) {
$ret[] = $val[$attr[0]][0];
}
}
return $ret;
}

COMA: Oracle-Tabellen zwischen Instanzen kopieren

Mit den nachfolgenden SQL-Anweisungen lassen sich mit einem Tool wie dem SQLDeveloper, Tabellen zwischen zwei verschiedenen Oracle-Instanzen kopieren,gültige Verbindungen zu den Instanzen vorrausgesetzt.Ausgangspunkt im SQLDeveloper ist jeweils die Zielinstanz.

Beispiel 1: von SERVICE nach INTERNET


create table WEB.WTR_UFZ
as select * from WEB.WTR_UFZ@testsystem

Beispiel 2: von INTERNET nach SERVICE


create table WEB.WTR_UFZ
as select * from WEB.WTR_UFZ@internet

COMA: Oracle-Tabellen zwischen Instanzen kopieren

Mit den nachfolgenden SQL-Anweisungen lassen sich mit einem Tool wie dem SQLDeveloper, Tabellen zwischen zwei verschiedenen Oracle-Instanzen kopieren,gültige Verbindungen zu den Instanzen vorrausgesetzt.Ausgangspunkt im SQLDeveloper ist jeweils die Zielinstanz.

Beispiel 1: von SERVICE nach INTERNET


create table WEB.WTR_UFZ
as select * from WEB.WTR_UFZ@testsystem

Beispiel 2: von INTERNET nach SERVICE


create table WEB.WTR_UFZ
as select * from WEB.WTR_UFZ@internet

Montag, 11. Januar 2010

Javascript: Objektorientierung und Drag and Drop (Teil 2)

Vererbung

Im zweiten Teil geht es um die Vererbung, ich habe u.a. in den Kommentaren den Begriff Klassen verwendet (natürlich gibt es in Javascript keine Klassen in dem Sinne), da ich aber versucht habe Strukturen nachzubilden, wie sie aus Java bzw. C# bekannt sind, erklärt sich das Ganze so besser.

Ob eine Verkettung der drei definierten Klassen möglich ist, gilt es noch auszutesten!

Javascript im HEAD (u.a. Objektinstanzierung):

window.onload = Init;

function Init() {
// neues Objekt der Subklasse instanzieren
var dragObj = new DragById("dragable_1");
// weiterere moegliche Instanzierung
//var dragObj = new DragInFrame(316, 92);

// Events öffentlichen Methoden aus
// dem instanziertem Objekt zuweisen
document.getElementById("dragpanel").onmousedown =
dragObj.startDrag;
document.getElementById("dragpanel").onmousemove =
dragObj.Drag;
document.getElementById("dragpanel").onmouseup =
dragObj.endDrag;
}
Javascript im HEAD (die Basisklasse):

function DragObj() {
// Variable zur Rückgabe
// von öffentlichen Methoden (Pattern)
var that = {};
// Objektvariablen
this.movie = null;
this.startX = 0;
this.startY = 0;
this.start_drag = false;

// öffentliche Methoden
that.startDrag = function(e) {
// Browserweiche
if(!e) { // IE
e = window.event;
this.movie = e.srcElement;
}
else
this.movie = e.target;

this.startY =
e.screenY - parseInt(this.movie.style.top);
this.startX =
e.screenX - parseInt(this.movie.style.left);

this.start_drag = true;
}

that.Drag = function(e) {
if(this.start_drag) {
if(!e)
e = window.event;

var newX = e.screenX - this.startX;
var newY = e.screenY - this.startY;

this.movie.style.left = newX + "px";
this.movie.style.top = newY + "px";

document.title = "X: " + newX + " Y: " + newY;
}
}

that.endDrag = function() {
this.start_drag = false;
}

return that;
}
Javascript im HEAD (die Subklassen):

function DragById(objId) {
// Konstruktor der Basisklasse aufrufen
this.constructor();
// öffentliche Methode der Basisklasse überschreiben
this.startDrag = function(e) {
if(document.getElementById(objId)) {
this.movie = document.getElementById(objId);

this.startY =
e.screenY - parseInt(this.movie.style.top);
this.startX =
e.screenX - parseInt(this.movie.style.left);

this.start_drag = true;
}
}
}
// Initialisierung der Vererbung
DragById.prototype = new DragObj();

// weitere abgeleitete Klasse definieren
function DragInFrame(frameWidth, frameHeight) {
// Konstruktor der Basisklasse aufrufen
this.constructor();
// öffentliche Methode der Basisklasse überschreiben
this.Drag = function(e) {
if(this.start_drag) {
if(!e)
e = window.event;

var newX = e.screenX - this.startX;
var newY = e.screenY - this.startY;

if(newX > 0 && newX < frameWidth)
this.movie.style.left = newX + "px";
if(newY > 0 && newY < frameHeight)
this.movie.style.top = newY + "px";

document.title = "X: " + newX + " Y: " + newY;
}
}
}
// Initialisierung der Vererbung
DragInFrame.prototype = new DragObj();
HTML im BODY:

<img src="html.gif"
style="position:absolute; top:0; left:0;"
onmousedown="return false;"
onmousemove="return false;"
width="129" height="108" id="dragable_1" />
Quelltext

Javascript: Objektorientierung und Drag and Drop (Teil 2)

Vererbung

Im zweiten Teil geht es um die Vererbung, ich habe u.a. in den Kommentaren den Begriff Klassen verwendet (natürlich gibt es in Javascript keine Klassen in dem Sinne), da ich aber versucht habe Strukturen nachzubilden, wie sie aus Java bzw. C# bekannt sind, erklärt sich das Ganze so besser.

Ob eine Verkettung der drei definierten Klassen möglich ist, gilt es noch auszutesten!

Javascript im HEAD (u.a. Objektinstanzierung):

window.onload = Init;

function Init() {
// neues Objekt der Subklasse instanzieren
var dragObj = new DragById("dragable_1");
// weiterere moegliche Instanzierung
//var dragObj = new DragInFrame(316, 92);

// Events öffentlichen Methoden aus
// dem instanziertem Objekt zuweisen
document.getElementById("dragpanel").onmousedown =
dragObj.startDrag;
document.getElementById("dragpanel").onmousemove =
dragObj.Drag;
document.getElementById("dragpanel").onmouseup =
dragObj.endDrag;
}
Javascript im HEAD (die Basisklasse):

function DragObj() {
// Variable zur Rückgabe
// von öffentlichen Methoden (Pattern)
var that = {};
// Objektvariablen
this.movie = null;
this.startX = 0;
this.startY = 0;
this.start_drag = false;

// öffentliche Methoden
that.startDrag = function(e) {
// Browserweiche
if(!e) { // IE
e = window.event;
this.movie = e.srcElement;
}
else
this.movie = e.target;

this.startY =
e.screenY - parseInt(this.movie.style.top);
this.startX =
e.screenX - parseInt(this.movie.style.left);

this.start_drag = true;
}

that.Drag = function(e) {
if(this.start_drag) {
if(!e)
e = window.event;

var newX = e.screenX - this.startX;
var newY = e.screenY - this.startY;

this.movie.style.left = newX + "px";
this.movie.style.top = newY + "px";

document.title = "X: " + newX + " Y: " + newY;
}
}

that.endDrag = function() {
this.start_drag = false;
}

return that;
}
Javascript im HEAD (die Subklassen):

function DragById(objId) {
// Konstruktor der Basisklasse aufrufen
this.constructor();
// öffentliche Methode der Basisklasse überschreiben
this.startDrag = function(e) {
if(document.getElementById(objId)) {
this.movie = document.getElementById(objId);

this.startY =
e.screenY - parseInt(this.movie.style.top);
this.startX =
e.screenX - parseInt(this.movie.style.left);

this.start_drag = true;
}
}
}
// Initialisierung der Vererbung
DragById.prototype = new DragObj();

// weitere abgeleitete Klasse definieren
function DragInFrame(frameWidth, frameHeight) {
// Konstruktor der Basisklasse aufrufen
this.constructor();
// öffentliche Methode der Basisklasse überschreiben
this.Drag = function(e) {
if(this.start_drag) {
if(!e)
e = window.event;

var newX = e.screenX - this.startX;
var newY = e.screenY - this.startY;

if(newX > 0 && newX < frameWidth)
this.movie.style.left = newX + "px";
if(newY > 0 && newY < frameHeight)
this.movie.style.top = newY + "px";

document.title = "X: " + newX + " Y: " + newY;
}
}
}
// Initialisierung der Vererbung
DragInFrame.prototype = new DragObj();
HTML im BODY:

<img src="html.gif"
style="position:absolute; top:0; left:0;"
onmousedown="return false;"
onmousemove="return false;"
width="129" height="108" id="dragable_1" />
Quelltext

Freitag, 8. Januar 2010

AJAX: HTML-Element für Autovervollständigung

Nachdem ich nach einigem Suchen kein stabiles Element für eine AJAX-Autocomplete Funktion gefunden habe, hier mein Mix aus einem Text- und Listenfeld.

Zum Test einfach etwas eingeben (ohne Datenanbindung).


var charCode = 0; // Tastencode aus beiden Steuerelementen
var optText = null; // Textfeld
var optList = null; // Listenfeld
var topOpt = false; // Hilfsvariable zum Steuern des Uebergangs
var oldText = ""; // Vorwert aus Textbox merken

function Init(obj) {
if(optList) // Falls noch andere Liste offen
//CloseList(false); // IE hängt sich auf
optList.style.display = 'none';

optText = obj;
optList = GetSelect(optText); // SELECT-Element ermitteln
// geerbte Breite des Eingabefeldes an SELECT-Element weitergebn
optList.style.width = optText.offsetWidth + "px";
// Variable charCode setzen
document.onkeydown = GetKeyCode;
}
function OpenList() {
oldText = optText.value; // Wert für Abbruch merken

if(charCode == 27) { // ESC
optList.style.display = 'none'; // Liste wieder zu machen
return;
}
if(charCode == 13) { // ESC
optList.style.display = 'none'; // Liste wieder zu machen
// Event valuefixed auslösen
return;
}

if(optText.value.length > 0) { // ist etwas im Textfeld
topOpt = true; // Pfeiltaste nach oben soll Textfeld aktivieren

with(optList) {
// bei diesen Tasten Liste anzeigen
if(
charCode == 8 || // Backspace
charCode == 40 || // Pfeil nach unten
charCode == 46 || // Delete
(charCode >= 48 && charCode <= 57) || // 0-9
(charCode >= 65 && charCode <= 90) || // a-z
charCode == 109 || // -
charCode == 190 || // .
charCode == 59 || // ü
charCode == 192 || // ö
charCode == 219 || // ß
charCode == 222 // ä
) {
style.display = 'block'; // Liste anzeigen
selectedIndex = -1; // nichts auswaehlen
}
}
}
else
CloseList(false); // wurde z.B. alles geloescht, Liste schliessen

// Übergang zur Liste bei...
if(charCode == 40 && // ... Pfeiltaste nach unten
optList.style.display == 'block') { // und Liste offen

optText.value = optList.options[0].value; // Textbox aktualisieren
optList.focus(); // Liste aktivieren
optList.selectedIndex = 0; // ersten Eintrag auswählen
}
}
function CloseList(setOpt) {
if(setOpt && (optList.options.length != optList.selectedIndex + 1)) {
optText.value = optList.value; // Listenwert ins Textfeld
// Event valuefixed auslösen
}
else {
optText.value = oldText;
oldText = null;
}
optText.focus(); // Textfeld aktivieren
optList.style.display = 'none'; // Liste ausschalten
}
function CancelSelect() {
optList.style.display = 'none'; // Liste ausschalten
optText.value = oldText; // gemerkten Text einsetzen
optText.focus(); // Textfeld aktivieren
}
function CtrlList() {

if(charCode == 13) // Enter
CloseList(true);
if(charCode == 27) // ESC
CancelSelect();
if((charCode == 38 || charCode == 40) && // Pfeiltaste oben unten
optList.options.length != optList.selectedIndex + 1) // nicht letzte Option
optText.value = optList.value;

if(charCode != 38) // nicht Pfeiltaste nach oben
topOpt = false;

// Pfeiltaste nach oben und oberster Eintrag ausgewaehlt
if(charCode == 38 && optList.selectedIndex == 0) {
if(topOpt) { // beim ersten Mal noch nichts machen
optList.style.display = 'none'; // Liste ausschalten
optText.focus(); // Textfeld aktivieren
}
else
topOpt = true; // um beim zweiten Pfeiltaste nach oben
} // Steuerelement zu wechseln
}
function GetKeyCode(e) {
if (!e)
e = window.event;
charCode = e.keyCode;
}
function GetSelect(obj) {
var count = 0;
do {
var elem = obj.nextSibling;
obj = elem;

count++;
if(count > 3) break;
} while(elem.type != "select-one")

return elem;
}
function FixValue() {
// TODO: Event valuefixed auslösen
// aktives Element oder Tastencodes prüfen
}
CSS im HEAD:

input.autocomplete {
width: inherit;
}
input.autocomplete {
display: block;
}
select.autocomplete {
display: none;
position: absolute;
}
#autocomplete1 {
float: left;
width: 200px;
}
#autocomplete2 {
float: left;
width: 200px;
}
.lastopt {
background-color: lightgray;
}
HTML im BODY:

<div id="autocomplete1">
<input type="text" name="autocomplete2" class="autocomplete" onclick="this.focus();" onfocus="Init(this)" onkeyup="OpenList();" onblur="FixValue();" tabindex="2" />
<select size="4" class="autocomplete" onclick="CloseList(true);" onkeyup="CtrlList();">
<option value="Peter">Peter</option>
<option value="Peters">Peters</option>
<option value="Petersen">Petersen</option>
<option value="Petersohn">Petersohn</option>
<option class="lastopt" title="Schließen">⇑</option>
</select>
</div>
Download komplettes Beispielkomplettes Beispiel