diff --git a/Rezepte_v1.2.xlsx b/Rezepte_v1.2.xlsx index 149080c..b643372 100644 Binary files a/Rezepte_v1.2.xlsx and b/Rezepte_v1.2.xlsx differ diff --git a/introduction.tex b/introduction.tex index 16143e8..02e38d4 100644 --- a/introduction.tex +++ b/introduction.tex @@ -1,3 +1,5 @@ +%!TEX ROOT = ./main.tex + \section*{Vorwort} \addcontentsline{toc}{section}{Vorwort} diff --git a/kekse.py b/kekse.py index 53aaf16..3731ddc 100755 --- a/kekse.py +++ b/kekse.py @@ -1,38 +1,41 @@ #!/usr/bin/env python3 -from openpyxl import Workbook -from openpyxl import load_workbook -import sys import os +import re + +from openpyxl import load_workbook, Workbook +from openpyxl.worksheet.worksheet import Worksheet - -def escape_latex (content): - content=content.replace("⁄","/") - content=content.replace("℔", "\ lb") - content=content.replace("½", "$\\frac{1}{2}$") - content=content.replace("¼", "$\\frac{1}{4}$") - content=content.replace("¾", "$\\frac{3}{4}$") - content=content.replace("\n", "\\\\\n") - content=content.replace("°", "$^\circ$") - content = content.replace("&", "\&") +def escape_latex(content): + content = content.replace("⁄", "/") + # content = content.replace("℔", r"\ lb") + content = content.replace("½", "$\\frac{1}{2}$") + content = content.replace("¼", "$\\frac{1}{4}$") + content = content.replace("¾", "$\\frac{3}{4}$") + content = content.replace("\n", "\n\n") + content = content.replace("°", r"$^\circ$") + content = content.replace("&", r"\&") content = content.replace("ö", "ö") + + content = re.sub(r'(\d) (\d+)/(\d+)', r'$\1\\frac{\2}{\3}$', content) + content = re.sub(r'(\d+)/(\d+)', r'$\\frac{\1}{\2}$', content) + content = re.sub(r'([\d$]g?) ?- ?([\d$])', '\\1--\\2', content) + content = content.replace("$ ", r"$\,") + return content # Define output file -f_latex = open("rezepte.tex","w+") +f_latex = open("rezepte.tex", "w+") +f_latex.write("%!TEX ROOT = ./main.tex\n\n") # Load cookbook -cb = load_workbook('/home/sebastian/Projekte/Kochbuch/kekse.xlsx', data_only=1) - +cb: Workbook = load_workbook('kekse.xlsx', data_only=True) sheets = cb.sheetnames -ws = None - - # Find worksheet with recipes -ws = cb.get_sheet_by_name("Rezepte") +ws: Worksheet = cb["Rezepte"] # Variables to store information while parsing @@ -51,8 +54,7 @@ ingredients = {} ingredients_unit = {} ingredients_comment = {} -ingredients_other_row = 0 - +ingredients_other_row = 0 # Other fields type_row = 0 @@ -75,236 +77,234 @@ for column in ws.columns: for cell in column: # Find row of type of recipe - if(cell.value=="Art"): + if cell.value == "Art": type_row = cell.row legend_row = cell.row legend_col = cell.column - if(cell.column == legend_col): + if cell.column == legend_col: # Find row of recipe name, this is in the row with 'Zutaten' - if(cell.value == "Zutaten"): + if cell.value == "Zutaten": name_row = cell.row - ingredients_row_start = cell.row +1 + ingredients_row_start = cell.row + 1 in_ingredients = True - # Find position of ingredients - if(cell.value == "Hauptaromen"): + if cell.value == "Hauptaromen": aroma_row = cell.row # Find position of source - if(cell.value == "Quelle"): + if cell.value == "Quelle": source_row = cell.row # Instructions - if(cell.value== "Anleitung"): + if cell.value == "Anleitung": instructions_row = cell.row # Check if we are at end of ingredients - if(cell.value== "Sonstiges (Deko)"): + if cell.value == "Sonstiges (Deko)": ingredients_other_row = cell.row in_ingredients = False # Make list of all ingredients and their units - if(cell.row >= ingredients_row_start and in_ingredients): + if cell.row >= ingredients_row_start and in_ingredients: string = cell.value - if("(" in string and ")" in string): - ingredients[cell.row] = (cell.value.split('(')[0].rstrip()) - ingredients_unit[cell.row] = (cell.value.split('(')[1].split(')')[0].rstrip()) - ingredients_comment[cell.row] = (cell.value.split(')')[1].rstrip()) + if "(" in string and ")" in string: + m = re.match(r'^([^(\n]*)(?: \((\S+ [^)]+)\))?(?: \(([^)]+)\))?$', cell.value) + assert m + ingredients[cell.row] = m.group(1) + ingredients_unit[cell.row] = m.group(3) + ingredients_comment[cell.row] = m.group(2) else: - ingredients[cell.row] = (string) - ingredients_unit[cell.row] = ("") - ingredients_comment[cell.row] = ("") - + ingredients[cell.row] = string + ingredients_unit[cell.row] = "" + ingredients_comment[cell.row] = "" # Further instructions - if(cell.value== "Backzeit (Minuten)"): + if cell.value == "Backzeit (Minuten)": baking_time_row = cell.row - if(cell.value== "Backtemperatur Umluft (Grad)"): + if cell.value == "Backtemperatur Umluft (Grad)": baking_temperature_row = cell.row - if(cell.value== "Ruhezeit (Minuten)"): + if cell.value == "Ruhezeit (Minuten)": resting_time_row = cell.row - if(cell.value== "Anzahl (ca.)"): + if cell.value == "Anzahl (ca.)": number_row = cell.row - if(cell.value== "Besonderheiten"): + if cell.value == "Besonderheiten": specials_row = cell.row # Years - if(cell.value == 2013): + if cell.value == 2013: first_year_row = cell.row last_year_row = cell.row first_year = 2013 - if(first_year_row > 0 and cell.value == "Kommentare zur Bearbeitung."): + if first_year_row > 0 and cell.value == "Kommentare zur Bearbeitung.": # cell.row -2 instead of -1 to ignore current year 2021 - last_year_row = cell.row-2 - + last_year_row = cell.row - 2 + # By now, we should have found everything in the legend - - + ##### # Parse recipe # Go through worksheet vertically, starting with the first column # If right of legend, then it must be a recipe - if(cell.column > legend_col): + if cell.column > legend_col: # Obtain information of recipe in the right order, so that we can directly write it to the tex-file. # Name of recipe - content = (ws._get_cell(name_row, cell.column).value) - if(content != "None\n" and content != None): - f_latex.write(str("\\begin{minipage}{\\textwidth}\n")) + content = ws.cell(name_row, cell.column).value + if content != "None\n" and content is not None: + f_latex.write("\\newpage\n") - #if (content[-5:]=="(Oma)"): + # if (content[-5:]=="(Oma)"): # content="Omas " + content[:-6] - f_latex.write(str("\section{%s}\\vspace{0.5cm}\n" % content)) + f_latex.write("\\section{%s}\\vspace{0.5cm minus 0.5cm}\n" % content) - f_latex.write(str("\\begin{tabular}{lll}\n")) + f_latex.write("\\begin{tabular}{lll}\n") # Aroma - content = (ws._get_cell(aroma_row, cell.column).value) - if(content != "None\n" and content != None): - f_latex.write(str("\\faHeart & \\textbf{Hauptzutat} & %s" % content)) - - f_latex.write(str("\\index{\\textbf{%s}}" % content.replace(", ", "}} \\index{\\textbf{"))) + content = ws.cell(aroma_row, cell.column).value + if content != "None\n" and content is not None: + f_latex.write("\\faHeart & \\textbf{Hauptzutat} & %s" % content) + + f_latex.write("\\index{\\textbf{%s}}" % content.replace(", ", "}} \\index{\\textbf{")) f_latex.write("\\\\\n") # Type - content = (ws._get_cell(type_row, cell.column).value) - if(content != "None\n" and content != None): - f_latex.write(str("\\faEye & \\textbf{Form} & %s" % content)) - f_latex.write(str("\\index[formen]{\\textbf{%s}}" % content.replace(", ", "}} \\index[formen]{\\textbf{"))) + content = ws.cell(type_row, cell.column).value + if content != "None\n" and content is not None: + f_latex.write("\\faEye & \\textbf{Form} & %s" % content) + f_latex.write("\\index[formen]{\\textbf{%s}}" % content.replace(", ", "}} \\index[formen]{\\textbf{")) f_latex.write("\\\\\n") # Source - content = (ws._get_cell(source_row, cell.column).value) - if(content != "None\n" and content != None): - f_latex.write(str("\\faBook & \\textbf{Quelle} & %s" % content)) - f_latex.write("\\\\\n") + content = ws.cell(source_row, cell.column).value + if content != "None\n" and content is not None: + f_latex.write("\\faBook & \\textbf{Quelle} & %s" % content) + f_latex.write("\\\\\n") # Specials - content = (ws._get_cell(specials_row, cell.column).value) + content = ws.cell(specials_row, cell.column).value if content == "(vegan)" or content == "(Vegan)": - content="Vegan möglich" + content = "Vegan möglich" if content == "(zuckerfrei)" or content == "(Zuckerfrei)": - content="Zuckerfrei möglich" - if(content != "None\n" and content != None): - f_latex.write(str("\\faStar & \\textbf{Besonderheiten} & %s" % content)) - f_latex.write(str("\\index[specials]{\\textbf{%s}}" % content.replace(", ", "}} \\index[specials]{\\textbf{"))) - f_latex.write("\\\\\n") + content = "Zuckerfrei möglich" + if content != "None\n" and content is not None: + f_latex.write("\\faStar & \\textbf{Besonderheiten} & %s" % content) + f_latex.write("\\index[specials]{\\textbf{%s}}" % content.replace(", ", "}} \\index[specials]{\\textbf{")) + f_latex.write("\\\\\n") # Baking - content1 = str(ws._get_cell(baking_time_row, cell.column).value) - content2 = str(ws._get_cell(baking_temperature_row, cell.column).value) + content1 = str(ws.cell(baking_time_row, cell.column).value) + content2 = str(ws.cell(baking_temperature_row, cell.column).value) - if((content1 != "None" and content1 != None and content1 != "0") or (content2 != "None" and content2 != None and content2 != "0")): - f_latex.write(str("\\Oven & \\textbf{Backzeit} &")) - if(content1 != "None" and content1 != None and content1 != "0"): - if(content1[-4:]=="Min."): + if (content1 != "None" and content1 is not None and content1 != "0") or (content2 != "None" and content2 is not None and content2 != "0"): + f_latex.write("\\Oven & \\textbf{Backzeit} &") + if content1 != "None" and content1 is not None and content1 != "0": + if content1[-4:] == "Min.": content1 = content1[:-4] - f_latex.write(str("%s Minuten bei " % content1)) + content1 = re.sub(r'(\d) ?- ?(\d)', '\\1--\\2', content1) + f_latex.write("%s Minuten bei " % content1) else: - f_latex.write(str(" bei")) - if(content2 != "None" and content2 != None and content2 != "0"): - f_latex.write(str(" %s~$^\circ$C" % content2)) + f_latex.write(" bei") + if content2 != "None" and content2 is not None and content2 != "0": + f_latex.write(" %s~$^\circ$C" % content2) f_latex.write("\\\\\n") # Resting time - content = str(ws._get_cell(resting_time_row, cell.column).value) - if(content != "None" and content != None and content != "0"): - f_latex.write(str("\\faClockO & \\textbf{Ruhezeit} &")) - if(content[-1:]=="h"): - f_latex.write(str(" %s Stunden" % content[:-1])) + content = str(ws.cell(resting_time_row, cell.column).value) + if content != "None" and content is not None and content != "0": + f_latex.write("\\faClockO & \\textbf{Ruhezeit} &") + if content[-1:] == "h": + f_latex.write(" %s Stunden" % content[:-1]) else: - f_latex.write(str("%s Minuten" % content)) + f_latex.write("%s Minuten" % content) f_latex.write("\\\\\n") # Amount - content = (ws._get_cell(number_row, cell.column).value) - if(content != "None\n" and content != None): - f_latex.write(str("\\faHashtag & \\textbf{Anzahl} & %s Stück\\\\\n" % content)) + content = ws.cell(number_row, cell.column).value + if content != "None\n" and content is not None: + f_latex.write("\\faHashtag & \\textbf{Anzahl} & %s Stück\\\\\n" % content) # Years year = first_year count = 0 output = "\\faCalendar & \\textbf{Gebacken} &" - for i in range (first_year_row, last_year_row+1): - content = (ws._get_cell(i, cell.column).value) - if(content != "None\n" and content != None): + for i in range(first_year_row, last_year_row + 1): + content = ws.cell(i, cell.column).value + if content != "None\n" and content is not None: # Cookie was baked in year output = output + " " + str(year) + "," - count +=1 + count += 1 year += 1 - if(count == 0): + if count == 0: output = output + " Noch nie gebacken" else: output = output[:-1] - f_latex.write(str(output+"\\\\\n")) - - if(count > 0): - f_latex.write(str("\\faLineChart & \\textbf{Häufigkeit} & " + str(round(100/(year-first_year)*count))+"\\%\\\\\n")) - - f_latex.write(str("\\end{tabular}\n")) + f_latex.write(str(output + "\\\\\n")) + if count > 0: + f_latex.write("\\faLineChart & \\textbf{Häufigkeit} & " + str(round(100 / (year - first_year) * count)) + "\\,\\%\\\\\n") + f_latex.write("\\end{tabular}\n") # List of Ingredients - f_latex.write(str("\\subsection*{Zutaten}\n")) + f_latex.write("\\subsection*{Zutaten}\n") - f_latex.write(str("\\begin{compactitem}\n")) - for i in range (ingredients_row_start, ingredients_other_row): - content = str(ws._get_cell(i, cell.column).value) - if(content != "None\n" and content != None and content != "None"): + f_latex.write("\\begin{multicols}2\\raggedright\n") + f_latex.write("\\begin{compactitem}\n") + for i in range(ingredients_row_start, ingredients_other_row): + number = str(ws.cell(i, cell.column).value) + if number != "None\n" and number is not None and number != "None": - #content = content + ingredients_unit[i-ingredients_row_start] + ingredients[i-ingredients_row_start] - - # Add unit and whitespaces if needed - if (ingredients_unit[i] !="g"): - content = content + " " - if (ingredients_unit[i] != ""): - content = content + ingredients_unit[i] + " " - - # Add Ingredient name - if (ingredients[i] == "Ei"): - if(content == "1 "): - content = content + "Ei" - else: - content = content + "Eier" + # Add unit and whitespaces + if not ingredients_unit[i]: + unit = "" + elif ingredients_unit[i][0].islower(): + unit = "\\," + ingredients_unit[i] else: - content = content + ingredients[i] + unit = "~" + ingredients_unit[i] + + # Add Ingredient name + label = ingredients[i] + if ingredients[i] == "Ei": + unit = "" + if number == "1": + label = "Ei" + else: + label = "Eier" + # Add comment if available - if(ingredients_comment[i] != ""): - content = content + "; " + ingredients_unit[i] + if ingredients_comment[i]: + label += r" \penalty-10(" + ingredients_comment[i] + ")" - content=escape_latex(content) + label = escape_latex(label) + f_latex.write("\\item %s%s %s \n" % (number, unit, label)) - f_latex.write(str("\\item %s \n") % content) - - f_latex.write(str("\\end{compactitem}\n\\vspace{0.2cm}\n")) + f_latex.write("\\end{compactitem}\n") + f_latex.write("\\end{multicols}\n") + f_latex.write("\\vspace{0.2cm minus 0.2cm}\n") # Other ingredients - content = (ws._get_cell(ingredients_other_row, cell.column).value) - - if(content != "None\n" and content != None and content != "None"): - content = escape_latex(content) - f_latex.write("\\textit{Außerdem:} %s \n" % content) + content = ws.cell(ingredients_other_row, cell.column).value + if content != "None\n" and content is not None and content != "None": + content = escape_latex(content) + f_latex.write("\\textit{Außerdem:} %s \n" % content) # Instructions - content = (ws._get_cell(instructions_row, cell.column).value) - if(content != "None\n" and content != None): - content=escape_latex(content) - - f_latex.write(str("\\subsection*{Anleitung} %s\n" % content)) - - f_latex.write(str("\\end{minipage}\n\n")) - f_latex.write(str("\\vspace{2cm}\n")) - + content = ws.cell(instructions_row, cell.column).value + if content != "None\n" and content is not None: + content = escape_latex(content) + content = re.sub(r'/([a-z])', r'/\\allowbreak{}\1', content, flags=re.I) + content = re.sub(r'(\d) ([a-z])', r'\1~\2', content, flags=re.I) + f_latex.write("\\subsection*{Anleitung} %s\n" % content) + f_latex.write("\\vspace{2cm minus 1cm}\n") # That's all, so close files f_latex.close() diff --git a/main.pdf b/main.pdf index c16f2bf..0c32194 100644 Binary files a/main.pdf and b/main.pdf differ diff --git a/main.tex b/main.tex index 370d8fc..15b103d 100644 --- a/main.tex +++ b/main.tex @@ -1,7 +1,12 @@ \documentclass[a4paper, 12pt, twoside, toc=flat, toc=sectionentrywithdots, BCOR=1cm]{scrartcl} +\usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} -\usepackage[german]{babel} % Silbentrennung +\usepackage[ngerman]{babel} % Silbentrennung +% Use A5 (for mobile) +% \usepackage[a5paper,margin=1em,bottom=5em]{geometry} + +\usepackage{hyperref} \usepackage{mdframed} \usepackage{anyfontsize} \usepackage{adjustbox} @@ -13,13 +18,14 @@ \usepackage{fontawesome} \usepackage{cookingsymbols} -% Schusterjungen und Hurenkinder unterdrücken -\widowpenalty = 10000 -\displaywidowpenalty = 10000 -\clubpenalty = 10000 +\DeclareUnicodeCharacter{2114}{\ensuremath{\mathchar'26\mkern-9mul\mkern-2mu\mathchar'26\mkern-9mub}} -\addtokomafont{section}{\normalfont \Huge \bfseries}{\sffamily} -\addtokomafont{subsection}{\normalfont \Large \bfseries}{\sffamily} +% Schusterjungen und Hurenkinder unterdrücken +\widowpenalty=5000 +\clubpenalty=5000 + +\addtokomafont{section}{\normalfont\Huge\bfseries}{\sffamily} +\addtokomafont{subsection}{\normalfont\Large\bfseries}{\sffamily} \let\labelitemi\labelitemii @@ -34,6 +40,7 @@ \include{title} \setkomafont{sectionentry}{\rmfamily} +\DeclareTOCStyleEntry[beforeskip=1em plus 1pt minus 1pt]{default}{section} \tableofcontents \include{introduction} @@ -44,4 +51,4 @@ \printindex[formen] \printindex[specials] -\end{document} \ No newline at end of file +\end{document} diff --git a/title.tex b/title.tex index b3fb391..9020681 100644 --- a/title.tex +++ b/title.tex @@ -1,3 +1,4 @@ +%!TEX ROOT = ./main.tex \titlepage{ @@ -15,14 +16,16 @@ font={\fontsize{80}{70}\selectfont} \pagestyle{empty} \begin{adjustbox}{minipage=.6\textwidth,center} -\Large{\em ``Cookies! Me eat!''\par -\hfill --- Cookie Monster} +\Large\em ``Cookies! Me eat!''\par +\hfill --- Cookie Monster \end{adjustbox} -\vspace{3em} +\vfill \begin{flushright} -\includegraphics[width=10cm]{figures/coati.pdf} +\includegraphics[ + width=.666\textwidth,height=.4\textheight,keepaspectratio +]{figures/coati.pdf} \end{flushright} \vspace{-1em} @@ -52,8 +55,8 @@ Sarah Wedrich \setlength{\parindent}{0pt} ~\\ -\vspace{5cm} -\bigbreak +\vspace*{0cm plus .3fill} + \huge{Plätzchen}\par \smallbreak \textit{\LARGE{Ein Kompendium}}\par @@ -61,7 +64,7 @@ Sarah Wedrich \begin{center}{\large{\textit{ Sarah Wedrich\\}}} -\vspace{9cm} +\vspace*{0cm plus .7fill} \Large{\today} \end{center}