Archive for the ‘Programmierung’ Category.

Angepasste CSV-Exporte aus Excel

Basierend auf meinem letzten Artikel zum Thema Excel und CSV hier ein kurzes Beispiel, wie man aus Excel heraus Daten in ziemlich beliebigem Format (hier Komma als Spaltentrenner, Punkt als Dezimalzeichen) exportieren kann.

Ausgangspunkt ist eine kleine Excel-Datei mit vier Spalten und drei Zeilen.

Der VBA Code, adaptiert von excel-easy.com und codevba.com, exportiert diese in eine CSV Datei (im ANSI-Encoding), wenn der Spalten-Index der exportierten Spalte kleiner ist als die Breite der Range, dann wird ein Komma nach der Spalte eingefügt, sonst (am Ende der Range) ein Zeilenumbruch.

Option Explicit
Sub Schaltfläche1_Klicken()
 
    Dim fso, f, currentColumn
    Dim rng As Range, cell As Range
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set f = fso.OpenTextFile("E:\SearchReplaceVBA\export.csv", 2, True)
 
    ' https://www.excel-easy.com/vba/examples/loop-through-defined-range.html
    ' http://codevba.com/excel/for_each_cell_in_range.htm
 
 
    Set rng = Sheets(1).Range("A1:D3")
 
    For Each cell In rng.Cells
        With cell
            ' Debug.Print .Address & ":" & .Value & ":" & .Row & ":" & .Column
            currentColumn = .Column
            f.write (Replace(.Value, ",", "."))
            If currentColumn < rng.Columns.Count Then
                f.write (",")
            Else
                f.write (vbNewLine)
            End If
 
        End With
    Next cell
 
End Sub

Ergebnis

Feld A,Feld B,Feld C,Feld D
88.4599201649139,9.76226327089422,AAA,45.4279124487558
22.6480222965468,82.5612661495282,BBB,96.7699232025441

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Mit VBA suchen und ersetzen in Textdateien

Heute mal mal mit Excel und VBA. Ziel ist es, in einer Textdatei (komma-separiert, Punkt als Dezimalzeichen) Platzhalter durch Werte zu ersetzen, ohne dass die Datei dabei von Excel kaputt „optimiert“ wird.

Die Excel-Datei sieht dabei so aus:

Einfach nur ein paar Werte untereinander, Dezimaltrenner ist das Komma.

CSV-Quelldatei „Quelle.csv“:

SpalteA,SpalteB,SpalteC
FeldA,WertA,1.12
FeldB,WertB,1.23
FeldC,WertC,1.34
FeldD,WertD,1.45
FeldE,WertE,1.56
FeldF,WertF,1.67
FeldG,WertG,1.78
FeldH,WertH,1.89
FeldI,WertI,1.90
FeldJ,WertJ,1.95

Hinter dem Buttom im Excel liegt der folgende VBA/VBS Code, den ich bei http://www.office-loesung.de gefunden und adaptiert habe.

Option Explicit
 
Sub Schaltfläche1_Klicken()
 
    Dim fso, f, text
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set f = fso.OpenTextFile("E:\SearchReplaceVBA\Quelle.csv", 1)
    text = f.ReadAll
 
    text = Replace(text, "WertA", Replace(Cells(2, 3).Value, ",", "."))
    text = Replace(text, "WertB", Replace(Cells(3, 3).Value, ",", "."))
    text = Replace(text, "WertC", Replace(Cells(4, 3).Value, ",", "."))
    text = Replace(text, "WertD", Replace(Cells(5, 3).Value, ",", "."))
    text = Replace(text, "WertE", Replace(Cells(6, 3).Value, ",", "."))
    text = Replace(text, "WertF", Replace(Cells(7, 3).Value, ",", "."))
    text = Replace(text, "WertG", Replace(Cells(8, 3).Value, ",", "."))
    text = Replace(text, "WertH", Replace(Cells(9, 3).Value, ",", "."))
    text = Replace(text, "WertI", Replace(Cells(10, 3).Value, ",", "."))
    f.Close
 
    Set f = fso.OpenTextFile("E:\SearchReplaceVBA\Ziel.csv", 2, True)
    f.Write (text)
    f.Close
 
End Sub

Das Ergebnis „Ziel.csv“ sieht dann so aus:

SpalteA,SpalteB,SpalteC
FeldA,2.9502085126608,1.12
FeldB,73.1026744983578,1.23
FeldC,55.250551974564,1.34
FeldD,33.2285937834519,1.45
FeldE,42.2559662206547,1.56
FeldF,24.6506686140567,1.67
FeldG,54.0201369859298,1.78
FeldH,26.9352342768415,1.89
FeldI,51.1782693678183,1.90
FeldJ,87.9325752371774,1.95

Es geht natürlich noch viel eleganter, indem man zum Beispiel Ranges nutzt, als Proof-of-Concept reicht dies jedoch schon aus.

Mit named Ranges würde die Lösung so aussehen:

Option Explicit
 
Sub Schaltfläche1_Klicken()
 
    Dim fso, f, text
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set f = fso.OpenTextFile("E:\SearchReplaceVBA\Quelle.csv", 1)
    text = f.ReadAll
 
    text = Replace(text, "WertA", Replace(Range("FeldA").Value, ",", "."))
    text = Replace(text, "WertB", Replace(Range("FeldB").Value, ",", "."))
    text = Replace(text, "WertC", Replace(Range("FeldC").Value, ",", "."))
    text = Replace(text, "WertD", Replace(Range("FeldD").Value, ",", "."))
    text = Replace(text, "WertE", Replace(Range("FeldE").Value, ",", "."))
    text = Replace(text, "WertF", Replace(Range("FeldF").Value, ",", "."))
    text = Replace(text, "WertG", Replace(Range("FeldG").Value, ",", "."))
    text = Replace(text, "WertH", Replace(Range("FeldH").Value, ",", "."))
    text = Replace(text, "WertI", Replace(Range("FeldI").Value, ",", "."))
    text = Replace(text, "WertJ", Replace(Range("FeldJ").Value, ",", "."))
 
    f.Close
 
    Set f = fso.OpenTextFile("E:\SearchReplaceVBA\Ziel.csv", 2, True)
    f.Write (text)
    f.Close
 
 
End Sub

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Mit WinRAR Dateien einzeln packen und verschlüsseln

Gelegentlich ist es praktisch, Aufgaben auf der Kommandozeile zu erledigen. Das Packen von n Dateien in separate verschlüsselte Archive gehört dazu. Der folgende Code packt jede XLSX Datei in einem Verzeichnis in ein entsprechendes RAR und verschlüsselt es mit dem Passwort „ABCDE“. Verschlüsselte ZIP Archive lassen sich meines Wissens nach nicht damit erstellen!

For /F %%a IN ('DIR /B *.xlsx') DO (
 CALL "C:\winrar\rar.exe" a -pABCDE %%~na.rar %%~na.xlsx
)

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Mailman Spammer mit Python blocken – Teil 2

Ausgehend von meinem ersten Artikel zu diesem Thema habe ich jetzt noch eine Erweiterung des Skripts vorgenommen. Als Spammer erkannte E-Mail-Adressen werden jetzt auch automatisch geblockt.

Dazu suche ich alle „Dauerhaft von der Liste verbannen“ Checkboxen — ihre Namen beginnen alle mit „ban-“ — und klicke sie.

from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
from selenium.common.exceptions import NoSuchElementException
 
opts = Options()
browser = Firefox(executable_path=r"C:\geckodriver-v0.27.0\geckodriver.exe",
                  options=opts)
browser.implicitly_wait(3)
 
browser.get('<url>')
search_form = browser.find_element_by_name('adminpw')
search_form.send_keys('<password>')
search_form.submit()
 
try:
    field = browser.find_element_by_name('discardalldefersp')
    field.click()
    browser.implicitly_wait(3)
    submit = browser.find_element_by_name('submit')
    submit.click()
except NoSuchElementException:
    print('No new messages to be discarded')
 
browser.implicitly_wait(3)
 
fields = browser.find_elements_by_xpath("//input[@value='3']")
emails = browser.find_elements_by_xpath('//td[contains(text(),"@")]')
banfields = browser.find_elements_by_xpath('//input[contains(@name,"ban-")]')
 
if len(fields) == 0:
    print('No new requests to be discarded, closing browser')
    browser.close()
else:
    if len(fields) == len(emails) and len(fields) == len(banfields) :
        zipped_list = list(zip(emails, fields, banfields))
 
        for i in zipped_list:
            email, field, banfield = i
            if not email.text.endswith(')'):
                field.click()
                banfield.click()

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

ESP32 unter Windows programmieren

Ein ESP32 ist ein sehr preiswerter Microcontroller, der aber einiges an Leistung „unter der Haube“ hat:

Wie kann man ihn unter Windows programmieren? Ich mache es wie folgt:

  1. Arduino IDE von https://www.arduino.cc/ installieren
  2. In den Voreinstellungen unter „Zusätzliche Boardverwalter-URLs“ die folgende URL hinzufügen: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  3. Boardverwalter-URL

  4. Unter Boardverwalter nach „ESP“ suchen und das Paket installieren
  5. ESP

  6. Eigenen Code oder Demo-Code schreiben/kompilieren und auf den ESP hochladen. Bei mir hat es mit den folgenden Einstellungen geklappt, zusätzlich musste ich aber beim Upload (nach dem Drücken des Upload-Knopfs) einmal den Boot-Button auf dem ESP drücken.
  7. Upload-Settings

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Siemens Nixdorf VFD Displays ansteuern mit Python

Vor einigen Monaten habe ich mir günstig auf Ebay ein Siemens Nixdorf BA 63 USB Display gekauft, das VFD (vacuum fluorescent display) Technologie für die Anzeige nutzt und 2×20 Zeichen bietet.

Als passendste Python-Bibliothek nutze ich https://github.com/stephanemouton/VFD-WCN, die Anleitung zur Einrichtung wird im github sehr gut beschrieben.

Hier der Quellcode, der die Ausgabe im Bild erzeugt:

from vfdpos import *
factory=WincorNixdorfDisplayFactory()
VFDs = factory.get_vfd_pos()
MyVFD = VFDs[0]

MyVFD.clearscreen()

MyVFD.poscur(1, 1)
MyVFD.write_msg("Hallo")
MyVFD.write_msg("Welt")
MyVFD.write_msg("1234567abcd\r")
MyVFD.poscur(2, 1)
MyVFD.write_msg("ABCDEFüäößi")

MyVFD.close()

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Fortnite teilweise blockieren – Erweiterung um Status

This entry is part 2 of 2 in the series Pi-Hole

Im ersten Artikel zu diesem Thema hatte ich schon beschrieben, wie man mit Pi-Hole DNS Lookups so unterbinden kann, dass man Fortnite oder andere Zeitfresser temporär blockieren kann. In diesem Teil erweitern wir das Skript um eine Statusabfrage. Dazu fügen wir einfach eine Route hinzu, die die URL mit dem Parameter /status abfragt. Dann wird der Inhalt der epicstatus.txt abgefragt, die von den Routen /on und /off mit dem Zeitstempel versehen wurde.

import os
from datetime import datetime
from flask import Flask
 
app = Flask(__name__)
 
@app.route('/')
def index():
    return('<h1>Use /off and /on to enable/disable blocking, /status to get epic.log</h1>')
 
@app.route('/<param>')
def setter(param):
    if param=='status':
        with open('/home/pi/epicstatus.txt') as f:
            content = f.read()
            return '<h2>' + content + '</h2>'
    if param=='off':
        os.system("/usr/local/bin/pihole regex '.*\.epicgames.com' > /home/pi/epic.log")
        now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        with open('/home/pi/epicstatus.txt','w') as ausgabe:
            ausgabe.write(now + ' off')
        return '<h1>Turning off Fortnite</h1>'
    elif param=='on':
        os.system("/usr/local/bin/pihole regex -d '.*\.epicgames.com' > /home/pi/epic.log")
        now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        with open('/home/pi/epicstatus.txt','w') as ausgabe:
            ausgabe.write(now+ ' on')
        return '<h1>Turning on Fortnite</h1>'

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Liste meiner genutzten VSC-Plugins

Neben UltraEdit, Notepad++, Emacs, etc. nutze ich auch Visual Studio Code. Hier die Liste der wichtigsten von mir genutzten Plugins:

  • German Language Pack for Visual Studio Code für deutsche Menüs
  • Render Line Endings, um zwischen LF und CRLF umzuschalten
  • Python für die Python-Unterstützung
  • LaTeX Workshop
  • Graphviz (dot) language support for Visual Studio Code für gv
  • Graphviz Preview für ebendas
  • Encryptor for VS Code, Text mit AES 256 zu verschlüsseln
  • Bracket Pair Colorizer um zueinandergehörige Klammern zu markieren

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Dateien kopieren, zippen und löschen mit Python

Hier ein kurzes Beispiel, wie man mit Python-Modulen Dateien kopieren, zippen und löschen kann.

import zipfile
from shutil import copyfile
from os import unlink
 
# copy file
copyfile('dtk-authoryear.bbx'  , './dtk-bibliography/dtk-authoryear.bbx')
copyfile('dtk-authoryear.dbx'  , './dtk-bibliography/dtk-authoryear.dbx')
copyfile('dtk-bibliography.pdf', './dtk-bibliography/dtk-bibliography.pdf')
copyfile('dtk-bibliography.tex', './dtk-bibliography/dtk-bibliography.tex')
 
# create the zip file
with zipfile.ZipFile('dtk-bibliography.zip', 'w', zipfile.ZIP_DEFLATED) as z:
    z.write('./dtk-bibliography/README.md')
    z.write('./dtk-bibliography/dtk-authoryear.bbx')
    z.write('./dtk-bibliography/dtk-authoryear.dbx')
    z.write('./dtk-bibliography/dtk-bibliography.pdf')
    z.write('./dtk-bibliography/dtk-bibliography.tex')
 
# delete copied files
unlink('./dtk-bibliography/dtk-authoryear.bbx')
unlink('./dtk-bibliography/dtk-authoryear.dbx')
unlink('./dtk-bibliography/dtk-bibliography.pdf')
unlink('./dtk-bibliography/dtk-bibliography.tex')

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Mailman Spammer mit Python blocken

Für Dante e.V. betreue ich einige E-Mail-Listen auf mailman-Basis, die seit einigen Tagen von Spammern geflutet werden. Jeden Tag sind dutzende bis hunderte Aufnahme-Requests in der Liste, die ich manuell wegwerfen müsste. Nachdem ich dies einmal händisch getan hatte, musste eine automatische Lösung gefunden werden.

Die Lösung bestand darin, einen Treiber für Firefox („geckodriver“) zu installieren, der das Fernsteuern des Browsers erlaubt. Dann kann mittels selenium Modul die Steuerung aus Python heraus erfolgen. Unten der wesentliche Quellcode als Basis für eigene Arbeiten, den Teil zum Erkennen von legitimen Anfragen habe ich weggelassen.

Nachtrag vom 25.10.2020: Siehe auch die Erweiterung unter https://www.uweziegenhagen.de/?p=4420

# -*- coding: utf-8 -*-
"""
https://www.edureka.co/community/47679/is-it-possible-to-run-headless-browser-using-python-selenium
"""
 
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
 
opts = Options()
#opts.set_headless() # Ich will sehen, wie selenium arbeitet
#assert opts.headless  # Operating in headless mode
browser = Firefox(executable_path=r"C:\Users\Uwe\Downloads\geckodriver-v0.27.0-win64\geckodriver.exe", options=opts)
browser.implicitly_wait(3)
 
# einloggen
browser.get('<url des mailman admin panels')
search_form = browser.find_element_by_name('<passwortfeld_ID>')
search_form.send_keys('<adminpasswort>')
search_form.submit()
 
#wegwerfen Button pro Zeile
fields = browser.find_elements_by_xpath("//input[@value='3']")
#email Adresse des Spammers
emails = browser.find_elements_by_xpath('//td[contains(text(),"@")]')
 
if len(fields) == len(emails):
    zipped_list = list(zip(emails, fields))
 
    for i in zipped_list:
        email, field = i
        field.click()

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website