Author Archive

Vortragsfolien „Briefvorlagen erstellen mit LaTeX und scrlttr2“

Hier die Folien von meinem Vortrag zum Thema „Briefvorlagen erstellen mit LaTeX und scrlttr2“, gehalten auf der Dante e.V. Vereinstagung in Darmstadt.

Alle Code-Beispiele sowie der Quelltext der Folien selbst sind Teil des PDF, dazu nutze ich das attachfile-Paket. Mit einem einfachen \newcommand Befehl baue ich dann den \ta Befehl, der als Parameter nur den Dateinamen entgegennimmt und im PDF dann ein rotes klickbares Paragraph-Symbol setzt.

\usepackage{attachfile}
\newcommand{\ta}[1]{\textattachfile[color=1 0 0]{#1}{\textparagraph}}

Vortragsfolien

Das github-Repository liegt unter https://github.com/UweZiegenhagen/scrlttr2_darmstadt

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Grafische Benutzeroberfläche für Docker

Synology hat für seine Geräte ein Docker-GUI entwickelt, was die Arbeit mit Docker ein wenig vereinfacht.

Docker selbst bietet solche Funktionen nicht meines Wissens nach nicht an, mit Portainer gibt es aber ein Docker-Image selbst, das eine GUI über den Browser bereitstellt.

Die Installation ist dabei sehr einfach

docker volume create portainer_data
docker run -d -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

Unter Port 9000 auf dem Docker-Server steht dann Portainer bereit.

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Minecraft Server im Docker laufen lassen

Nachdem ich auf meinem Synology-NAS bereits erfolgreich einen Minecraft-Server unter Docker laufen lasse, wollte ich heute mal den Sevrer unter „purem“ Docker starten.

Vom NAS-Docker weiß ich bereits, dass sowohl ein Port als auch ein Verzeichnis freigegeben sein sollten, um a) den Zugriff von anderen Rechnern zu ermöglichen und b) ein persistentes Verzeichnis für die Minecraft-Daten zu haben. Als Docker-Image nutze ich das von https://hub.docker.com/r/itzg/minecraft-server/. Auf der github-Seite steht auch schon alles, was man für den erfolgreichen Start benötigt.

docker run -d -it -e EULA=TRUE -p 25565:25565 -v /home/uwe/docker/minecraftdata:/data --name mc itzg/minecraft-server

Die Optionen stehen dabei für

  • -d: detached mode, also im Hintergrund
  • -it
  • eigentlich -i -t, lasse STDIN offen und füge Pseudo-TTY hinzu. Das bewirkt, das man per Shell reinkommt

  • -e
  • für Umgebungsvariablen, hier die End-User-License

  • -p
  • Port-Mapping, Port auf dem Docker-Server:Port im Container

  • -v
  • Volume-Mapping, Verzeichnis auf dem Docker-Server:Verzeichnis im Docker-Container

  • –name
  • Namen des zu erstellenden Containers

Docker zieht dann alles aus dem Netz und konfiguriert sich entsprechend…

(base) root@Sams18:~# docker run -d -it -e EULA=TRUE -p 25565:25565 -v /home/uwe/docker/minecraftdata:/data --name mc itzg/minecraft-server
Unable to find image 'itzg/minecraft-server:latest' locally
latest: Pulling from itzg/minecraft-server
4fe2ade4980c: Pull complete
6fc58a8d4ae4: Pull complete
d3e6d7e9702a: Downloading  12.92MB/54.8MB
9170f7184f6e: Downloading  16.64MB/62.09MB
712b0a9c3995: Download complete
d1c532702e4b: Download complete
6875113ceea1: Download complete
76dc7bb21202: Downloading  1.195MB/2.229MB
ea8424983368: Waiting
3a34ffca3cb1: Waiting

Mittels docker start mc bzw. docker stop mc wird dann der Server gestartet und gestoppt.

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Python-Skripte per Drag & Drop triggern

Hier ein Beispiel, wie man per Drag & Drop Python-Skripte ausführen kann.

In eine entsprechende Batch-Datei kommt der folgende Aufruf

C:\WinPython-32bit-3.3.5.5\python-3.3.5\python.exe dragdrop.py %1 > error.log 2>&1

In die dragdrop.py kommt dann der eigentliche Python-Code, hier wird die „gedroppte“ Excel-Datei in CSV umgewandelt.

import sys
import os
import pandas as pd

droppedFile = sys.argv[1]
filename = os.path.splitext(droppedFile)[0]

df = pd.read_excel(droppedFile, skiprows=[0,1,2,3])
df.to_csv(filename +'.csv', sep=';', index=False)

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Erste Schritte mit Docker

Nachdem ich auf meinem NAS (einem Synology DS918+) bereits Erfahrungen mit Docker sammeln konnte, will ich jetzt mehr über die Grundlagen lernen. Ziel ist es mittelfristig, Node Red laufen zu lassen, um einige Aspekte unseres trauten Heims zu automatisieren. Zur Entwicklung nehme ich einen älteren Intel NUC mit i3-Prozesser, auf dem ein Ubuntu Bionic läuft, später landet vielleicht alles auf dem Raspi, den ich in die Unterversorgung gehängt habe.

In diesem Artikel geht es jetzt um die Installation, im wesentlichen folge ich dabei der Anleitung von https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04

1) Herausfinden, welche Ubuntu-Version man hat?

lsb_release -a

gibt in der letzten Zeile den Namen mit aus.

2)

sudo apt update

sudo apt install apt-transport-https ca-certificates curl software-properties-common

aktualisiert die Quellen und fügt einige benötigte Programme hinzu, so sie noch nicht installiert sind.

3)

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

holt den public PGP-Key von der Docker-Seite, da wir von dort und nicht aus den Bionic-Quellen von Canonical installieren.

4)

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt update

fügt die Quellen hinzu und aktualisiert die apt-Quellen

5)

sudo apt install docker-ce

installiert dann Docker.

Wie kann man die Installation prüfen? Mit „Hello World“ 🙂

sudo docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Im nächsten Artikel zum Thema erläutern wir dann die wichtigsten Docker-Befehle für die Kommandozeile.

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Spam-Löschen mit UIPath

Vor ein paar Tagen habe ich begonnen, mich etwas intensiver mit RPA (Robotic Process Automation) zu beschäftigen. Nachdem ich mit Katalan Studio schon recht einfach das Spam-Löschen in den von mir betreuten Mailing-Listen automatisieren konnte, wollte ich dieses Mal mit einer dedizierten RPA-Software arbeiten. Ich habe mich dabei für UIPath entschieden, da wir a) auch im Büro damit arbeiten und b) diese Software der Marktführer für RPA-Tools ist.

Ich habe ein neues Projekt begonnen und starte mit einer Sequenz. In Schritt 1 wird der IE geöffnet (nicht Edge, wird anscheinend noch nicht unterstützt) und die URL der Mailingliste geladen.

Öffnen des Browsers in UIPath (URL muss in Anführungszeichen)

Innerhalb des Browser-Scope nutze ich ich dann den „Type Into“ Befehl, um das Passwort einzugeben. Das anschließend notwendige „Return“ bzw. „Enter“ kann man definieren, in dem man rechts vom Eingabefeld das Plus-Zeichen anklickt und den entsprechenden Befehl selektiert, hier „Enter“.

Eingabe des Passworts

Der nächste Punkt ist entscheidend, denn es gibt zwei mögliche Szenarien: entweder sind Spam-Nachrichten vorhanden oder auch nicht. Ich nutze zu Identifikation des Szenarios die „Alle mit Entscheidung ‚aufschieben“ Inputbox mit der Name-Property „discardalldefersp“. (Alternativ könnte man sicher auch den Senden-Button dafür nutzen.)

Ist diese vorhanden, dann soll sie und anschließend der Senden-Button „Alle Daten senden“ angeklickt werden. Ist sie nicht vorhanden, dann soll der Bot sich nur ausloggen (da er dies auch tun muss, wenn Spam-Nachrichten gelöscht wurden, muss dies nicht innerhalb der Bedingung geschehen.)

Mit der Box wird entschieden, ob Spam-Nachrichten vorhanden sind oder nicht.

Ich nutze jetzt den „Element exists“ Befehl, um nach der Input-Box zu suchen.“WaitforReady“ sollte man auf None setzen, da sonst der Bot eventuell ewig darauf wartet, dass die Input-Box erscheint (TBD). Ich nutze noch eine boolean Variable, um den Status „Inputbox gefunden“ für meine folgende IF-Bedingung zu speichern. Dazu geht man in das „Exists“ Feld unter Output, drückt Strg-K und vergibt einen möglichst sprechenden Namen, ich habe „vBoolDiscard“ gewählt.

WaitForReady setze ich auf „None“, eine Output-Variable setze ich mit Strg-K => „NameDerVariablen“

Als nächste folgt die IF-Bedingung, die den Wert der eben gesetzten boolean Variablen prüft. Wenn der Wert TRUE ist, dann ist die Checkbox vorhanden und  soll angeklickt werden. Wenn sie nicht vorhanden ist, ist kein Spam vorhanden, der Bot kann sich ausloggen und den Tab schließen.

Rest der Sequenz: wenn die Inputbox vorhanden ist, dann wird sie angeklickt und mit Senden bestätigt. Ist sie nicht vorhanden, geschieht nichts. 

Fazit: Wenn man die Kniffe kennt (Erstelle eine Variable, warte nicht auf Input-Elemente), dann ist der Einstieg in RPA mit UIPath recht einfach. Ohne sie muss man schon die vorhandenen Tutorials recht intensiv lesen.


Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Checklisten setzen mit

Mit dem typed-checklist Paket lassen sich einfach komplexe Checklisten setzen, hier ein Beispiel aus der Dokumentation:

\documentclass{article}
\usepackage{typed-checklist}
\begin{document}
\begin{CheckList}{Goal}
\Goal{open}{I have a trendy haircut}
\begin{CheckList}{Task}
\Task{done}{find a hairdresser}
\Task{started}{make an appointment}
\Task{open}{go to the hairdresser}
\end{CheckList}
\Goal{achieved}{I have a typed checklist}
\end{CheckList}
\end{document}

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination.

Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Changelogs setzen mittels „changelog“ Paket

Mit dem changelog Paket gibt es eine komfortable Möglichkeit, changelogs in Dokumenten zu setzen. Hier ein Beispiel, entnommen der Dokumentation.

\documentclass[12pt,ngerman]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{booktabs}
\usepackage{babel}
\usepackage{graphicx}
\usepackage{csquotes}
\usepackage{paralist}
\usepackage{xcolor}
\usepackage[color]{changelog}
\begin{document}
 
\begin{changelog}[sectioncmd=\section,title={Versionshistorie}]
 
\begin{version}{0.9}
\added Really cool features
\end{version}
 
\begin{version}[date=2019-01-23]
\item A version with only a date
\end{version}
 
\begin{version}[v=1.1.0]
\item A version with no date
\end{version}
 
\begin{version}[v=1.0.1, yanked]
\item sasda
\end{version}
\end{changelog}
 
\end{document}

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination.

Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Zwei DIN A5 Seiten auf einer DIN A4 Seite setzen

Für meine Studentinnen und Studenten erstelle ich zu jeder Vorlesung eine kurze Wiederholung auf Basis der exam Klasse. Üblicherweise reicht ein DIN A5 Blatt, daher liegt es nahe, zwei DIN A5 Blätter auf ein DIN A4 Blatt zu drucken.

Um nicht den Text zweimal setzen zu müssen, gibt es zwei nützliche Lösungen (neben der Nutzung von Adobe Acrobat):


Duplizieren der Seite mittels pdftk:

Für pdftk habe ich eine kleine Batch-Datei duplicate.bat geschrieben, die dann mittels duplicate datei1.pdf datei2.pdf aufgerufen wird.


@echo off
pdftk %1 cat 1-end 1-end output %2


Duplizieren der Seiten in LaTeX mittels pgfpages

Über TSX (https://tex.stackexchange.com/questions/142187/compile-two-a5-pages-on-one-a4-page/142272) bin ich auf eine Lösung gestoßen, die im LaTeX-Lauf selbst die Seite dupliziert:

\documentclass[a4paper,ngerman,12pt]{article}
 
\usepackage{pgfpages}                                 % <— load the package
\pgfpagesuselayout{2 on 1}[a4paper,landscape,border shrink=5mm] % <— set options
 
\usepackage{atbegshi}  % duplicate the content at shipout time
\AtBeginShipout{%
  \pgfpagesshipoutlogicalpage{1}\copy\AtBeginShipoutBox
  \pgfpagesshipoutlogicalpage{2}\box\AtBeginShipoutBox
  \pgfshipoutphysicalpage
}
 
\usepackage{blindtext}
\begin{document}
 
\blindtext[3]
 
\end{document}

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination.

Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Python: Code-Rahmen für Auswertungen mit pandas

Für das „Rahmenwerk“ rund um eine Datenauswertung nutze ich immer den selben Code, der a) die Auswertung von Kommandozeilenparametern b) Zeitstempel und c) das Logging übernimmt. Geloggt wird auf STDOUT und in eine Datei.

import pandas as pd # pandas
import argparse # Kommandozeilenargumente
import logging # Logging
import sys # für das Logging
import time # für den Zeitstempel

# Zeitstempel
timestr = time.strftime('%Y%m%d') # '%Y%m%d-%H%M%S'

# Logger in Datei und auf die Konsole
logger = logging.getLogger("Logfile.log")
logger.propagate = False
logger.setLevel(logging.DEBUG)
 
fileHandler = logging.FileHandler(logger.name + '_' + timestr + ".log",mode='w')
fileHandler_format = logging.Formatter('%(asctime)s_%(levelname)s_%(message)s',datefmt='%H:%M:%S')
fileHandler.setFormatter(fileHandler_format)

consoleHandler = logging.StreamHandler(sys.stdout)
#formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
consoleHandler.setFormatter(fileHandler_format)

if logger.handlers:
    for handler in logger.handlers:
        logger.removeHandler(handler)

logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)

# Zum Auswerten der Kommandozeilenparameter (siehe Aufruf aus Excel)
# Definiere Parameter
parser = argparse.ArgumentParser("Was bin ich")
parser.add_argument('-c','--currentdate',dest='currentdate')
parser.add_argument('-l','--lastdate',dest='lastdate')
parser.add_argument('-o','--outputfile',dest='outputpath')

# verarbeite Kommandozeilenargumente

logger.info('Verarbeite die Kommandozeilenargumente')
args = parser.parse_args()

# no more "A value is trying to be set on a copy of a slice from a DF" warning
pd.options.mode.chained_assignment = None

print('args.currentdate', args.currentdate)
print('args.lastdate', args.lastdate)
print('args.outputpath', args.outputpath)

logging.shutdown()

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination.

Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website