我有一份文档,其中描述了如何装修我的房子。现在有人想要一份附加文档(在附录中和/或作为额外的 CSV 文件),其中包含所有窗户和门等的零件清单。
如何生成在文档内部调用的宏的表格和/或 CSV 文件?
例如我想写这样的文档:
\documentclass[final,a4paper,11pt,oneside,openany]{memoir}
\usepackage[naustrian]{babel}
\usepackage[thmmarks]{ntheorem}
\usepackage{thm-restate}
\newcounter{reqcounter}
\newtheorem{RQ}[reqcounter]{Neu}
\begin{document}
\chapter{Dachgeschoss}
\section{Wohnzimmer}
% I am searching for a macro to be used like:
%\fenster{130/150}{1 flg Drehkipp rechts}{Fixrahmen von innen abnehmbar}{}
\appendix
% After using \fenster several times, I can create a list somewhere else in the document:
%\listoffenster
\end{document}
在本地具有类似以下 LaTeX 代码的效果,RQ 被定义为定理以为每个要求获取一个数字:
\begin{RQ}
Fenster mit 3-Scheiben Isolierverglasung, mit Rolladen und Fensterbank. %fixed text
Ausmaße: 130/150. % from 1st argument
Ausführung: 1 flg Drehkipp rechts % from 2nd argument
Insektenschutz: Fixrahmen von innen abnehmbar % from 3rd argument
% from 4th argument
\textit{Farbe: Innen Weiß, Außen weiß; Beschlag: Silber.} %fixed text
\end{RQ}
并在附录中创建一个表格(在上面的示例中使用 \listoffenster)和/或外部 CSV 文件(第一行是静态标题):
Floor;Room;Size;Ausführung;Insektenschutz;Kommentar
Dachgeschoss;Wohnzimmer;130/150;1 flg Drehkipp rechts;Fixrahmen von innen abnehmbar;
其中“Dachgeschoss”是章节,“Wohnzimmer”是调用宏的部分。
答案1
由于 30000 个字符的限制,我需要将我的答案分成两部分。
这是我的回答的第二部分。
第1部分包含考虑、解释和想法。
第2部分包含第 1 部分中引用的可编译示例。
如果你想点赞,请点赞只有一个两部分。这可以防止不公平的声誉获取。如果你想要反对,就投票给你想反对的任何部分。
承诺的例子:
%\listfiles
%\errorcontextlines=10000
\documentclass[final,a4paper,11pt,oneside,openany]{memoir}
%\documentclass[final,a4paper,11pt,oneside,openany]{book}
\usepackage{datatool}
\usepackage{xparse}
\usepackage{hyperref}
\usepackage{atveryend}
\usepackage{rerunfilecheck}
\usepackage{verbatim}
\makeatletter
%========================================================================
% \immediategroup{<balanced text>}%
%------------------------------------------------------------------------
% A local scope wherein <balanced text> is carried out while \write,
% \closeout and \openout are patched to work in terms of \immediate.
%------------------------------------------------------------------------
\newcommand\immediategroup[1]{%
\begingroup
\@ifdefinable\MyStuffsavedwrite{\let\MyStuffsavedwrite\write}%
\@ifdefinable\MyStuffsavedopenout{\let\MyStuffsavedopenout\openout}%
\@ifdefinable\MyStuffsavedcloseout{\let\MyStuffsavedcloseout\closeout}%
\def\write{\immediate\MyStuffsavedwrite}%
\def\openout{\immediate\MyStuffsavedopenout}%
\def\closeout{\immediate\MyStuffsavedcloseout}%
#1%
\endgroup
}%
%========================================================================
% \DATABASEFILECreateIfNotExistent{<base-name of databases and of .csv-file>}%
% {<separator>}%
% {<delimiter>}%
% - Creates database of name: <base-name of databases and of .csv-file>DataFromPreviousLaTeXRun
% - Creates database of name: <base-name of databases and of .csv-file>DataToBeWrittenAtEndOfThisLaTeXRun
% These databases exist in TeX's memory during the LaTeX-run.
% - Triggers the writing of file <base-name of databases and of .csv-file>.csv
% at the end of the LaTeX-run from the content of the database
% <base-name of databases and of .csv-file>DataToBeWrittenAtEndOfThisLaTeXRun
% - Initializes Counter-macro \<base-name of databases and of .csv-file>DataToBeWrittenAtEndOfThisLaTeXRunCnt
% to 0. That counter-macro is to hold the value of the field "PrimaryKey" of the data-base
% <base-name of databases and of .csv-file>DataToBeWrittenAtEndOfThisLaTeXRun
% and is incremented always right before writing another line/row to the that database.
%
% The memory-database <base-name of databases and of .csv-file>DataFromPreviousLaTeXRun is
% used for retrieving data. In case the file <base-name of databases and of .csv-file>.csv
% exists that database is initialized by reading that file. Otherwise it is
% initialized empty.It is not modified during the LaTeX-run.
% The data stems from the previous LaTeX-run.
%
% The memory-database <base-name of databases and of .csv-file>DataToBeWrittenAtEndOfThisLaTeXRun is
% used for writing/storing entries during the LaTeX-run. It is initialized empty.
% It is modified during the LaTeX-run. At the end of the LaTeX-run it is saved as
% file <base-name of databases and of .csv-file>.csv .
%
% At the end of the LaTeX-run both databases are compared. If they differ, then
% something has changed and you are informed that you need to do another LaTeX-run.
%
% <separator> is the separator of values in the .csv-file. Usually this is comma (,)
% , but in your question you specified that you wish to use semicolon (;).
%
% <delimiter>: In case a value contains <separator> it needs to be nested
% between two instances of <delimiter>. <delimiter> usually is the quotes-character (").
%------------------------------------------------------------------------
\newcommand\DATABASEFILECreateIfNotExistent[3]{%
\DTLifdbexists{#1DataFromPreviousLaTeXRun}{}{%
\begingroup
\DTLsetseparator{#2}%
\DTLsetdelimiter{#3}%
\IfFileExists{#1.csv}{%
\DTLloaddb{#1DataFromPreviousLaTeXRun}{#1.csv}%
}{%
\DTLgnewdb{#1DataFromPreviousLaTeXRun}%
}%
\endgroup
}%
\DTLifdbexists{#1DataToBeWrittenAtEndOfThisLaTeXRun}{}{%
\DTLgnewdb{#1DataToBeWrittenAtEndOfThisLaTeXRun}%
% --- Counter-macro for primary-key of database ---
\expandafter\@ifdefinable\csname#1DataToBeWrittenAtEndOfThisLaTeXRunCnt\endcsname{%
\expandafter\long\expandafter\gdef\csname#1DataToBeWrittenAtEndOfThisLaTeXRunCnt\endcsname{0}%
}%
% -------------------------------------------------
\AfterLastShipout{%
% This will save the ..DataToBeWrittenAtEndOfThisLaTeXRun-
% database to file after the last \shipout. The last \shipout
% is triggered by \end{document}/\enddocument.
\immediategroup{%
\DTLsetseparator{#2}%
\DTLsetdelimiter{#3}%
\RerunFileCheck{#1.csv}{}{Database `#1' may have changed. Rerun LaTeX to get listings of database-entries etc right}%
\DTLsavedb{#1DataToBeWrittenAtEndOfThisLaTeXRun}{#1.csv}%
}%
%% Check if content of database-token-register stemming from
%% database-file of previous LaTeX-run differs from content of
%% database-token-register stemming from database-file of
%% the current LaTeX-run.
%% If so, something changed and you need to re-run LaTeX.
%% Probably this should be omitted with large databases.
%% Therefore this is turned into comments and a tesr via
%% \RerunFileCheck is used instead.
%\begingroup
%\DTLsetseparator{#2}%
%\DTLsetdelimiter{#3}%
%\DTLgcleardb{#1DataToBeWrittenAtEndOfThisLaTeXRun}%
%\DTLnewdbonloadfalse
%\DTLloaddb{#1DataToBeWrittenAtEndOfThisLaTeXRun}{#1.csv}%
%\edef\tempa{%
% \the\csname dtldb@#1DataFromPreviousLaTeXRun\endcsname
% \the\csname dtlkeys@#1DataFromPreviousLaTeXRun\endcsname
% \the\csname dtlrows@#1DataFromPreviousLaTeXRun\endcsname
% \the\csname dtlcols@#1DataFromPreviousLaTeXRun\endcsname
%}%
%\edef\tempb{%
% \the\csname dtldb@#1DataToBeWrittenAtEndOfThisLaTeXRun\endcsname
% \the\csname dtlkeys@#1DataToBeWrittenAtEndOfThisLaTeXRun\endcsname
% \the\csname dtlrows@#1DataToBeWrittenAtEndOfThisLaTeXRun\endcsname
% \the\csname dtlcols@#1DataToBeWrittenAtEndOfThisLaTeXRun\endcsname
%}%
%\ifx\tempa\tempb
% \endgroup
%\else
% \endgroup
% \@latex@warning@no@line{%
% Database `#1' may have changed.
% Rerun to get listings of entries etc right%
% }%
%\fi
}%
}%
}%
%=========================================================================
% Infrastructure for triggering a warning in case the value of a document-
% wide property was requested at a moment in time when the property didn't
% exist (yet).
%-------------------------------------------------------------------------
\AfterLastShipout{\PropertyValuesNotFound}%
\newcommand*\PropertyValuesNotFound{}%
\newcommand*\PropertyValuesNotFoundTrue{%
\gdef\PropertyValuesNotFound{\@latex@warning@no@line {There were undefined properties}}%
}%
\ExplSyntaxOn
%=========================================================================
% Property-List for properties that are to be maintained document-wide
% during the LaTeX-run. Values can change during the LaTeX-run.
% If you want to store the values which some properties have at a specific
% moment in time during the LaTeX-run, you can use the macro
% \DatabaseRowFromSomeOfThisDocumentsProperties
% for storing these properties' current values as another row of a
% database of name <base-name of databases and of .csv-file>DataToBeWrittenAtEndOfThisLaTeXRun
%-------------------------------------------------------------------------
\prop_new:N {\g__MyStuff_ThisDocumentsProperties_prop}
\prop_gput:Nnn \g__MyStuff_ThisDocumentsProperties_prop{Primary-Key}{0}
%=========================================================================
% expl3-scratch-variables:
%-------------------------------------------------------------------------
\tl_new:N {\l__MyStuff_ExtractedProperty_tl}
\clist_new:N{\l__MyStuff_PropertyNames_clist}
\bool_new:N \g__MyStuff_NewDatabaseRow_bool
\cs_new:Nn \__MyStuff_ExpandedDatabaseName: {}
%=========================================================================
% Set document-wide properties' values _globally_ by providing a
% <property1>=<value1>, <property2>=<value2>, ..., <propertyN>=<valueN>-list:
% \SetSomeOfThisDocumentsPropertiesFromKeyValList{%
% <property1>=<value1>, <property2>=<value2>, ..., <propertyN>=<valueN>
% }%
%
% If a property doesn't exist it is created anew automatically.
% If a property does exist, its value is overridden.
%-------------------------------------------------------------------------
\NewDocumentCommand{\SetSomeOfThisDocumentsPropertiesFromKeyValList}{m}{
\keyval_parse:NNn \__MyStuff_GSetSomeOfThisDocumentsPropertiesFromKeyValList:n
\__MyStuff_GSetSomeOfThisDocumentsPropertiesFromKeyValList:nn
{#1}
}
\cs_new:Nn \__MyStuff_GSetSomeOfThisDocumentsPropertiesFromKeyValList:n {
\__MyStuff_GSetSomeOfThisDocumentsPropertiesFromKeyValList:nn {#1}{\DTLstringnull}
}
\cs_new:Nn \__MyStuff_GSetSomeOfThisDocumentsPropertiesFromKeyValList:nn {
\group_begin:
\cs_set:Npn \protect { \noexpand\protect\noexpand }
\exp_args:Nnx \use:n
{
\exp_args:Nnx \use:n
{ \prop_gput:Nnn \g__MyStuff_ThisDocumentsProperties_prop }
{#1}
}
{#2}
% \prop_gput:Nxx \g__MyStuff_ThisDocumentsProperties_prop{#1}{#2}
\group_end:
}
%=========================================================================
% Create a row of a database
% <base-name of databases and of .csv-file>DataToBeWrittenAtEndOfThisLaTeXRun
% from current values of document-wide properties by specifying a comma-
% separated list of property-names.
% Names of properties will be used as names of fields/columns of the database.
% If a field/column doesn't yet exist in the database, it will be created automatically.
% If the database itself doesn't exist, it will be created automatically
% by \DATABASEFILECreateIfNotExistent. (That's why you need to specify
% <separator> and <delimiter>.)
% If a property doesn't exist, an error-message is raised and datatool's
% null-value for strings is provided as value to the database.
%
% \DatabaseRowFromSomeOfThisDocumentsProperties{<base-name of databases and of .csv-file>}%
% {<separator>}%
% {<delimiter>}%
% {<Property1>, <Property2>,..., <PropertyN>}%
%
%-------------------------------------------------------------------------
\NewDocumentCommand{\DatabaseRowFromSomeOfThisDocumentsProperties}{mmmm}{
\bool_gset_true:N \g__MyStuff_NewDatabaseRow_bool
\cs_set:Nx \__MyStuff_ExpandedDatabaseName: {#1DataToBeWrittenAtEndOfThisLaTeXRun}
\exp_args:Nx \DATABASEFILECreateIfNotExistent{#1}{#2}{#3}
\clist_set:Nn \l__MyStuff_PropertyNames_clist {#4}
\cs_gset:cpx {\__MyStuff_ExpandedDatabaseName: Cnt}
{\number\numexpr\use:c{\__MyStuff_ExpandedDatabaseName: Cnt}+1\relax}
\exp_args:Nnx \use:n
{
\prop_gput:Nnn \g__MyStuff_ThisDocumentsProperties_prop {PrimaryKey}
}
{\use:c{\__MyStuff_ExpandedDatabaseName: Cnt}}
% \prop_gput:Nxx \g__MyStuff_ThisDocumentsProperties_prop {PrimaryKey} {\use:c{\__MyStuff_ExpandedDatabaseName: Cnt}}
\__MyStuff_DatabaseEntryFromThisDocumentsProperty:n {PrimaryKey}
\clist_map_function:NN \l__MyStuff_PropertyNames_clist \__MyStuff_DatabaseEntryFromThisDocumentsProperty:x
}
\cs_new:Nn \__MyStuff_DatabaseEntryFromThisDocumentsProperty:n {
\prop_get:NnN \g__MyStuff_ThisDocumentsProperties_prop {#1} \l__MyStuff_ExtractedProperty_tl
\exp_args:NV \quark_if_no_value:nTF \l__MyStuff_ExtractedProperty_tl {
\protect\PropertyValuesNotFoundTrue
% I am too lazy to delve into expl3's l3msg
\@latex@warning{Macro~ \token_to_str:N\DatabaseRowFromSomeOfThisDocumentsProperties:\space
Property~`#1'~undefined~-~using~value~\DTLstringnull\space instead~-}
\tl_set:Nn \l__MyStuff_ExtractedProperty_tl {\DTLstringnull}
}{}
\__MyStuff_DatabaseRowFromPropertyAndValue:onV \__MyStuff_ExpandedDatabaseName: {#1} \l__MyStuff_ExtractedProperty_tl
}
\cs_generate_variant:Nn \__MyStuff_DatabaseEntryFromThisDocumentsProperty:n {x}
\cs_new:Nn \__MyStuff_DatabaseRowFromPropertyAndValue:nnn {
\DTLifhaskey{#1}{#2}{}{
\DTLaddcolumn{#1}{#2}
}
\bool_if:NTF \g__MyStuff_NewDatabaseRow_bool{
\DTLnewrow{#1}
}{}
\bool_gset_false:N \g__MyStuff_NewDatabaseRow_bool
\group_begin:
% \cs_set:Npn \protect { \noexpand\protect\noexpand }
\cs_set:Npn \protect { \token_to_str:N }
\exp_args:Nnx \use:n {\DTLnewdbentry{#1}{#2}} {#3}
\group_end:
}
\cs_generate_variant:Nn \__MyStuff_DatabaseRowFromPropertyAndValue:nnn{onV}
%=========================================================================
% Retrieve the current value of a document-wide property.
%
% \GetDocumentsPropertyValue{<Property>}
%
% If a property doesn't exist, an error-message is raised and the
% tokens \textsf{??} are provided.
%
% Not used in the following code. But I wasn't aware of that at the time
% of composing all this. Probably it may be useful in other scenarios.
%-------------------------------------------------------------------------
\NewDocumentCommand{\GetDocumentsPropertyValue}{m}{
\__GetDocumentsPropertyValue:x{#1}
}
\cs_new:Nn \__GetDocumentsPropertyValue:n {
\prop_get:NnN \g__MyStuff_ThisDocumentsProperties_prop {#1} \l__MyStuff_ExtractedProperty_tl
\exp_args:NV \quark_if_no_value:nTF \l__MyStuff_ExtractedProperty_tl {
\protect\PropertyValuesNotFoundTrue
% I am too lazy to delve into expl3's l3msg
\@latex@warning{Macro~\token_to_str:N\GetDocumentsPropertyValue:\space
Property~`#1'~undefined~-~using~value~\token_to_str:N\textsf{??}~instead~-}
\tl_set:Nn \l__MyStuff_ExtractedProperty_tl {\textsf{??}}
}{}
\tl_use:N \l__MyStuff_ExtractedProperty_tl
}
\cs_generate_variant:Nn \__GetDocumentsPropertyValue:n {x}
%=========================================================================
% Via datatool-package's \DTLforeach iterate on the rows
% of the database <base-name of databases and of .csv-file>DataFromPreviousLaTeXRun.
%
% If the database itself doesn't exist, it will be created automatically
% by \DATABASEFILECreateIfNotExistent. (That's why you need to specify
% <separator> and <delimiter>.)
%
% \DoWithDatabaseProperties{<base-name of databases and of .csv-file>}%
% {<separator>}%
% {<delimiter>}%
% [<condition>]%
% {<assign list>}%
% {<text>}%
%
% <base-name of databases and of .csv-file>, <separator> and <delimiter> are
% the same as above.
% <condition>, <assign list> and <text> are the same as with \DTLforeach
% of the datatool-package.
%-------------------------------------------------------------------------
\NewDocumentCommand\DoWithDatabaseProperties{mmmo}{
\exp_args:Nx \DATABASEFILECreateIfNotExistent {#1}{#2}{#3}
\IfNoValueTF{#4}{\exp_args:Nnx \use:n {\DTLforeach*}}
{\exp_args:Nnx \use:n {\DTLforeach*[{#4}]}}
{#1DataFromPreviousLaTeXRun}
}
\ExplSyntaxOff
\makeatother
%=========================================================================
% Now the individual building blocks of the infrastructure for managing
% document-wide properties via databases and .csv files are in place.
% They can now be used for implementing the macros at user level, which
% is straightforward:
%=========================================================================
% \ListOf...-commands can easily be implemented in terms of
% \DoWithDatabaseProperties.
%
% A scratch-switch which can be initialized by the \ListOf...-command
% and toggled by \DoWithDatabaseProperties's <text>-argument. This
% switch is intended to indicate whether at least one row of the
% database already ended up as an entry of the list.
%
% E.g., only in this case a heading for the list in question is needed.
% Only in this case starting/ending some environment is needed, e.g.,
% description or tabular.
%
\newif\ifNoDatabaseEntryEndedUpInTheListYet
\global\NoDatabaseEntryEndedUpInTheListYettrue
%=========================================================================
% An example of how to implement \ListOfFenster by means of
% nested description-environments and \DoWithDatabaseProperties (whose
% underlying macro is \DTLforeach):
%-------------------------------------------------------------------------
\newcommand\ListOfFenster{%
\global\NoDatabaseEntryEndedUpInTheListYettrue
\DoWithDatabaseProperties{Parts}{;}{"}%
[{\equal{Fenster}{\ArtDesTeils}}]%
{%
\PrimaryKey=PrimaryKey,%
\NummerDesTeils=NummerDesTeils,%
\ArtDesTeils=ArtDesTeils,%
\Stockwerkname=Stockwerkname,%
\Zimmer=Zimmer,%
\Ausmasze=Ausmasze,%
\Ausfuehrung=Ausfuehrung,%
\Insektenschutz=Insektenschutz,%
\Kommentar=Kommentar,%
\Destination=Destination%
}%
{%
\ifNoDatabaseEntryEndedUpInTheListYet
\global\NoDatabaseEntryEndedUpInTheListYetfalse
\section*{Liste der Fenster}%
\begin{description}%
\fi
\item[\hyperlink
{\Destination}%
{%
\PrintAssignListElement\NummerDesTeils
~(\PrintAssignListElement\Stockwerkname,
\PrintAssignListElement\Zimmer)%
}]\hfill\null
\begin{description}%
\AssignListElementDescriptionItem{\Ausmasze}{Maße}%
\AssignListElementDescriptionItem{\Ausfuehrung}{Ausführung}%
\AssignListElementDescriptionItem{\Insektenschutz}{Insektenschutz}%
\AssignListElementDescriptionItem{\Kommentar}{Kommentar}%
\end{description}%
}%
\ifNoDatabaseEntryEndedUpInTheListYet\else\end{description}\fi
}%
\newcommand\PrintAssignListElement[1]{\DTLifnull{#1}{\textsf{??}}{#1}}%
\newcommand\AssignListElementDescriptionItem[2]{%
\DTLifnullorempty{#1}{%
\DTLifnull{#1}{\item[{#2:}]\PrnProp\textsf{??}}{}%
}{%
\item[{#2:}]#1%
}%
}%
%=========================================================================
% Some elements of your database of parts shall come from the arguments
% of commands like \chapter or \section.
% One could patch these commands to also fulfill the purpose of
% setting the corresponding document-wide properties' values.
% Instead I define variants of these commands with slightly different
% names which set the corresponding document-wide properties' values
% and call the corresponding sectioning-commands:
%=========================================================================
\newcommand\FloorChapter[1]{%
\SetSomeOfThisDocumentsPropertiesFromKeyValList{Stockwerkname=#1}%
\chapter{#1}%
}
\newcommand\RoomSection[1]{%
\SetSomeOfThisDocumentsPropertiesFromKeyValList{Zimmer=#1}%
\section{#1}%
}%
%=========================================================================
% The \Fenster-Command sets some document-wide properties from its
% arguments, delivers an RQ-environment, sets some other document-wide
% property from the current value of the counter underlying the RQ-environment
% and then creates a(nother) database-row from the current values of
% the document-wide properties:
%=========================================================================
\newcommand\Fenster[4]{%
\SetSomeOfThisDocumentsPropertiesFromKeyValList{%
ArtDesTeils=Fenster,
Ausmasze=#1, Ausfuehrung=#2, Insektenschutz=#3, Kommentar=#4%
}%
\begin{RQ}
Fenster mit 3-Scheiben Isolierverglasung, mit Rolladen und Fensterbank.\\
Ausmaße: #1.\\
Ausführung: #2.\\
Insektenschutz: #3.\\
\textit{Farbe: Innen Weiß, Außen weiß; Beschlag: Silber.}%
\ifcat$\detokenize{#4}$\else\\Kommentar: #4\fi
\end{RQ}
\SetSomeOfThisDocumentsPropertiesFromKeyValList{%
NummerDesTeils=Neu\protect~\thereqcounter,
Destination=\csname @currentHref\endcsname
}%
\DatabaseRowFromSomeOfThisDocumentsProperties{Parts}{;}{"}{%
NummerDesTeils, ArtDesTeils, Stockwerkname, Zimmer, Ausmasze,
Ausfuehrung, Insektenschutz, Kommentar, Destination,
}%
}%
\usepackage[naustrian]{babel}
\usepackage[thmmarks]{ntheorem}
\usepackage{thm-restate}
\newcounter{reqcounter}
\newtheorem{RQ}[reqcounter]{Neu}
\begin{document}
\ListOfFenster
\FloorChapter{Erdgeschoss}
\RoomSection{Toilette}
\Fenster{50/80}{1 flg Keinkipp mitte}{Fixrahmen von aussen einsehbar}{Kommentar zu diesem Fenster}
\FloorChapter{Dachgeschoss}
\RoomSection{Wohnzimmer}
\Fenster{130/150}{1 flg Drehkipp rechts}{Fixrahmen von innen abnehmbar}{}
This is the content of the automatically created .csv-file \verb|Parts.csv|\,:
\begingroup
\tiny
\verbatiminput{Parts.csv}
\endgroup
And once more:
\ListOfFenster
\end{document}
.pdf 输出的图像:
Parts.csv
在 LaTeX 运行期间自动写入的文件:
PrimaryKey;NummerDesTeils;ArtDesTeils;Stockwerkname;Zimmer;Ausmasze;Ausfuehrung;Insektenschutz;Kommentar;Destination
1;Neu~1;Fenster;Erdgeschoss;Toilette;50/80;1 flg Keinkipp mitte;Fixrahmen von aussen einsehbar;Kommentar zu diesem Fenster;RQ.1
2;Neu~2;Fenster;Dachgeschoss;Wohnzimmer;130/150;1 flg Drehkipp rechts;Fixrahmen von innen abnehmbar;;RQ.2
TeX-distribution/format/documentclass/packages/files 正在使用 - 摘自 .log 文件,在取消注释 -command 时创建\listfiles
:
pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020) (preloaded format=pdflatex)
LaTeX2e <2020-10-01> patch level 4
L3 programming layer <2021-02-18>
memoir.cls -- 2020/10/04 v3.7n configurable book, report, article document class
(
Package abstract [2008/07/23] emulated by memoir.
Package appendix [2008/07/23] emulated by memoir.
Package booktabs [2016/05/16] emulated by memoir.
Package ccaption [2008/07/23] emulated by memoir.
Package changepage [2008/07/23] emulated by memoir.
Package chngcntr [2008/07/23] emulated by memoir.
Package chngpage [2008/07/23] emulated by memoir.
Package crop emulated by memoir.
Package enumerate [2008/07/23] emulated by memoir.
Package epigraph [2008/07/23] emulated by memoir.
Package ifmtarg [2008/07/23] emulated by memoir.
Package index [2008/07/23] emulated by memoir.
Package makeidx [2008/07/23] emulated by memoir.
Package moreverb [2008/07/23] emulated by memoir.
Package mparhack [2008/07/23] emulated by memoir.
Package needspace [2008/07/23] emulated by memoir.
Package newfile [2008/07/23] emulated by memoir.
Package nextpage [2008/07/23] emulated by memoir.
Package pagenote [2008/07/23] emulated by memoir.
Package parskip [2008/07/23] emulated by memoir.
Package patchcmd [2008/07/23] emulated by memoir.
Package setspace [2008/07/23] emulated by memoir.
Package shortvrb [2008/07/23] emulated by memoir.
Package showidx [2008/07/23] emulated by memoir.
Package titleref [2008/07/23] emulated by memoir.
Package titling [2008/07/23] emulated by memoir.
Package tocbibind [2008/07/23] emulated by memoir.
Package tocloft [2008/07/23] emulated by memoir.
Package tocvsec2 [2008/07/23] emulated by memoir.
Package verbatim [2008/07/23] emulated by memoir.
Package verse [2008/07/23] emulated by memoir.
)
aliasctr.sty -- 2020/08/01 v0.72
amsbsy.sty -- 1999/11/29 v1.2d Bold Symbols
amsgen.sty -- 1999/11/30 v2.0 generic functions
amsmath.sty -- 2020/09/23 v2.17i AMS math features
amsopn.sty -- 2016/03/08 v2.02 operator names
amstext.sty -- 2000/06/29 v2.01 AMS text
array.sty -- 2020/10/01 v2.5c Tabular extension package (FMi)
atbegshi-ltx.sty -- 2020/08/17 v1.0a Emulation of the original atbegshi package with kernel methods
atveryend-ltx.sty -- 2020/08/19 v1.0a Emulation of the original atvery package with kernel methods
auxhook.sty -- 2019-12-17 v1.6 Hooks for auxiliary files (HO)
babel.sty -- 2021/02/22 3.54 The Babel package
bigintcalc.sty -- 2019/12/15 v1.5 Expandable calculations on big integers (HO)
bitset.sty -- 2019/12/09 v1.3 Handle bit-vector datatype (HO)
datatool-base.sty -- 2019/09/27 v2.32 (NLCT)
datatool-fp.sty -- 2019/09/27 v2.32 (NLCT)
datatool.sty -- 2019/09/27 v2.32 (NLCT)
dcolumn.sty -- 2014/10/28 v1.06 decimal alignment package (DPC)
defpattern.sty -- 1994/10/12
delarray.sty -- 2014/10/28 v1.01 array delimiter package (DPC)
etexcmds.sty -- 2019/12/15 v1.7 Avoid name clashes with e-TeX commands (HO)
etoolbox.sty -- 2020/10/05 v2.5k e-TeX tools for LaTeX (JAW)
expl3.sty -- 2021-02-18 L3 programming layer (loader)
fp-addons.sty -- 1995/03/15
fp-basic.sty -- 1996/05/13
fp-eqn.sty -- 1995/04/03
fp-eval.sty -- 1995/04/03
fp-exp.sty -- 1995/04/03
fp-pas.sty -- 1994/08/29
fp-random.sty -- 1995/02/23
fp-snap.sty -- 1995/04/05
fp-trigo.sty -- 1995/04/14
fp-upn.sty -- 1996/10/21
gettitlestring.sty -- 2019/12/15 v1.6 Cleanup title references (HO)
hpdftex.def -- 2021-02-10 v7.00j Hyperref driver for pdfTeX
hycolor.sty -- 2020-01-27 v1.10 Color options for hyperref/bookmark (HO)
hyperref-langpatches.def -- 2021-02-10 v7.00j Hyperref: patches for babel languages
hyperref.sty -- 2021-02-10 v7.00j Hypertext links for LaTeX
iftex.sty -- 2020/03/06 v1.0d TeX engine tests
ifthen.sty -- 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC)
infwarerr.sty -- 2019/12/03 v1.5 Providing info/warning/error messages (HO)
intcalc.sty -- 2019/12/15 v1.3 Expandable calculations with integers (HO)
kvdefinekeys.sty -- 2019-12-19 v1.6 Define keys (HO)
kvoptions.sty -- 2020-10-07 v3.14 Key value format for package options (HO)
kvsetkeys.sty -- 2019/12/15 v1.18 Key value parser (HO)
l3backend-pdftex.def -- 2021-02-18 L3 backend support: PDF output (pdfTeX)
letltxmacro.sty -- 2019/12/03 v1.6 Let assignment for LaTeX macros (HO)
ltxcmds.sty -- 2020-05-10 v1.25 LaTeX kernel commands for general use (HO)
mem11.clo -- 2008/01/30 v0.3 memoir class 11pt size option
memhfixc.sty -- 2019/10/24 v1.18 nameref/hyperref package fixes for memoir class
nameref.sty -- 2021-04-02 v2.47 Cross-referencing by name of section
naustrian.ldf -- 2020/07/21 v2.12 German support for babel (post-1996 orthography)
ntheorem.sty -- 2011/08/15 1.33
parseargs.sty -- 2020/08/01 v0.72
pd1enc.def -- 2021-02-10 v7.00j Hyperref: PDFDocEncoding definition (HO)
pdfescape.sty -- 2019/12/09 v1.15 Implements pdfTeX's escape features (HO)
pdftexcmds.sty -- 2020-06-27 v0.33 Utility functions of pdfTeX for LuaTeX (HO)
puenc.def -- 2021-02-10 v7.00j Hyperref: PDF Unicode definition (HO)
refcount.sty -- 2019/12/15 v3.6 Data extraction from label references (HO)
rerunfilecheck.sty -- 2019/12/05 v1.9 Rerun checks for auxiliary files (HO)
substr.sty -- 2009/10/20 v1.2 Handle substrings
tabularx.sty -- 2020/01/15 v2.11c `tabularx' package (DPC)
textcase.sty -- 2019/09/14 v1.00 Text only upper/lower case changing (DPC)
thm-autoref.sty -- 2020/08/01 v0.72
thm-kv.sty -- 2020/08/01 v0.72
thm-listof.sty -- 2020/08/01 v0.72
thm-ntheorem.sty -- 2020/08/01 v0.72
thm-patch.sty -- 2020/08/01 v0.72
thm-restate.sty -- 2020/08/01 v0.72
thmtools.sty -- 2020/08/01 v0.72
uniquecounter.sty -- 2019/12/15 v1.4 Provide unlimited unique counter (HO)
url.sty -- 2013/09/16 ver 3.4 Verb mode for urls, etc.
xfor.sty -- 2009/02/05 v1.05 (NLCT)
xkeyval.sty -- 2020/11/20 v2.8 package option processing (HA)
xkeyval.tex -- 2014/12/03 v2.7a key=value parser (HA)
xparse-2020-10-01.sty -- 2020-10-01
xparse.sty -- 2021-01-09 L3 Experimental document command parser
答案2
由于 30000 个字符的限制,我需要将我的答案分成两部分。
这是我的回答的第一部分。
第1部分包含考虑、解释和想法。
第2部分包含第 1 部分中引用的可编译示例。
如果你想点赞,请点赞只有一个两部分。这可以防止不公平的声誉获取。如果你想要反对,就投票给你想反对的任何部分。
您的请求可以拆分成几个需要合并的方面:
您希望维护外部.csv 文件。
我建议采取以下方法:
通过 Nicola Talbot 博士的包裹数据工具从 LaTeX 运行开始维护二LaTeX 内存中的数据库:
一个内存数据库用于存储数据它将出现在 LaTeX 运行结束时的 .csv 文件中。 该数据库的内容在 LaTeX 运行结束时写入 .csv 文件中。
另一个内存数据库是通过读取 .csv 文件创建的这是在上一次 LaTeX 运行期间产生的。 该数据库用于检索数据用于创建.pdf 文件的输出。
这样,同时尝试在数据库中存储和从数据库中读取不会发生冲突,并且在 LaTeX 运行结束时产生的数据也可以在 LaTeX 运行开始时使用,尽管它源于上一次 LaTeX 运行,这意味着您需要多次 LaTeX 运行直到一切都匹配。
\refstepcounter
(这基本上与由命令/\label
/\ref
/等组成的 LaTeX 交叉引用机制的概念相同。\paggeref
不同之处在于数据库不是通过外部 .aux 文件维护,而是通过外部 .csv 文件维护。)在示例中第2部分这个答案维护一个数据库
⟨base name of databases and .csv‑file⟩DataToBeWrittenAtEndOfThisLaTeXRun
和一个数据库⟨base name of databases and .csv‑file⟩DataFromPreviousLaTeXRun
和一个.csv文件⟨base name of databases and .csv‑file⟩.csv
是由宏启动的
。\DATABASEFILECreateIfNotExistent{⟨base name of databases and .csv-file⟩}% {⟨separator⟩}% {⟨delimiter⟩}%
您希望维护零件列表。您可以将“零件”视为具有某些属性的集合。因此您需要机制来
- 通过名称引入新属性
- 设置这些属性的当前值
- 根据某些属性的当前值的集合创建数据库条目。
我建议一个类似于 LaTeX 的概念
\refstepcounter
。内部由分段命令( 、、 ...)\refstepcounter
调用,并设置通过宏、、等实现的属性值,这些属性值又被命令用于将条目写入 .aux 文件。\section
\caption
\@currentlabel
\@currentHref
\label
\newlabel
在示例中第2部分这个答案引入属性(如果尚未引入)并全局设置它们的当前值是通过宏完成的
。如果您未指定值,数据工具字符串的空值被假定。\SetSomeOfThisDocumentsPropertiesFromKeyValList{% ⟨propertyA⟩=⟨valueA⟩, ⟨propertyB⟩=⟨valueB⟩, ...% }%
表示属性名称的标记和表示属性值的标记都通过 expl3 的 x 扩展进行扩展。对于后者,我尝试考虑 LaTeX 2ε-\protect
机制。在示例中第2部分这个答案将属性的当前值集合存储为数据库的新行
⟨base name of databases and .csv‑file⟩DataToBeWrittenAtEndOfThisLaTeXRun
是通过宏完成的
。\DatabaseRowFromSomeOfThisDocumentsProperties{⟨base name of databases and .csv-file⟩}% {⟨separator⟩}% {⟨delimiter⟩}% {⟨propertyA⟩, ⟨propertyB⟩, ...}%
如果数据库
⟨base name of databases and .csv‑file⟩DataToBeWrittenAtEndOfThisLaTeXRun
尚不存在,则将重新创建它们,并在 LaTeX 运行结束时触发⟨base name of databases and .csv‑file⟩DataFromPreviousLaTeXRun
写入文件。⟨base name of databases and .csv‑file⟩.csv
如果该文件
⟨base name of databases and .csv‑file⟩.csv
在之前的 LaTeX 运行中已经存在,它的内容将被读取到数据库中⟨base name of databases and .csv‑file⟩DataFromPreviousLaTeXRun
,否则数据库⟨base name of databases and .csv‑file⟩DataFromPreviousLaTeXRun
将被视为空的。在 LaTeX 运行结束时,将比较两个数据库。如果它们不同,则表示发生了一些变化,并且会通知您需要再进行一次 LaTeX 运行。
⟨separator⟩
是 .csv 文件中值的分隔符。通常为逗号 (,
) ,但在您的问题中,您指定要使用分号 (;
)。⟨delimiter⟩
:如果值包含,⟨separator⟩
则需要将其嵌套在两个实例之间⟨delimiter⟩
。⟨delimiter⟩
通常是引号字符("
)。您的示例包含
\chapter{Dachgeschoss}
和\section{Wohnzimmer}
。似乎您的数据库的某些元素/某些属性的值来自分段命令的参数,例如\chapter
(这是为了设置属性“floor”的值)和\section
(这是为了设置属性“room”的值)。这意味着除了通常的用途之外,您希望为这些分段命令分配一个额外的用途,即表示随后提到的 parts/windows/Fenster 所具有的某些属性的值。这意味着这些分段命令也需要修补才能实现此目的。在我看来,这是最困难的方面,因为为了增加实现目的,命令需要更改/修补,而相关的分段命令也有带星号的变体和可选参数,例如,您没有指定在指定可选参数的情况下该怎么做。您需要一些基础设施来创建
\listof...
命令,这些命令通过迭代数据库来创建任何列表⟨base name of databases and .csv‑file⟩DataFromPreviousLaTeXRun
。在示例中第2部分这个答案的宏
是一个用于应用的包装器数据工具的\DoWithDatabaseProperties{⟨base name of databases and .csv‑file⟩}% {⟨separator⟩}% {⟨delimiter⟩}% [⟨condition⟩]% {⟨assign list⟩}% {⟨text⟩}%
更方便地访问数据库,\DTLforeach[⟨condition⟩]% {⟨database name}% {⟨assign list⟩}% {⟨text⟩}%
⟨base name of databases and .csv‑file⟩DataFromPreviousLaTeXRun
同时确保数据库(如果尚不存在)被创建,并且能够在将内容写入 .csv 文件时指定值⟨separator⟩
。⟨delimiter⟩
在
⟨assign list⟩
‑ 参数中,将这些属性的名称分配给宏,这些属性的值存储在数据库中,以便数据库具有具有相应名称的字段。在 ‑ 参数中,⟨text⟩
您可以使用这些宏来表示来自数据库行中单个字段的相应值。提供了一个临时开关
\ifNoDatabaseEntryEndedUpInTheListYet
。它可以通过 ‑命令初始化\ListOf...
并在\DoWithDatabaseProperties
的 ‑⟨text⟩
参数内切换。此开关旨在指示数据库中至少一行是否已成为列表的条目。例如,只有在这种情况下才需要列表的标题。例如,只有在这种情况下才需要启动/结束某些环境;例如,描述/表格。