daVidearl / jcomma
将CSV文件转换为一致的格式
Requires
- php: >=5.4
- components/jquery: 3.6.0
- components/jqueryui: 1.12.1
- mk-j/php_xlsxwriter: 0.38
README
jcomma将CSV(和TSV)文件转换为其他格式,并对其进行清理,使其不受CSV生成器的随意性影响。
实时版本在https://jcomma.davidearl.uk
CSV是一种真正糟糕的数据交换格式,特别是在国际间。然而,它在各种场景中无处不在,并且因为它对非程序员来说相对容易理解(部分原因是因为它忽略了问题),所以我们经常不得不处理我们不想处理的文件。
例如,银行经常生成包含以下内容的CSV文件:
- 每隔几条记录就有交错标题,
- 有多于一个的标题行,
- 在您只需要数字的地方有货币符号,
- 日期格式不合适或含糊不清,
- 括号或尾随减号作为负数,而普通人会把它们放在正常的负数位置,
- 正数(例如存款)在一列,而负数(例如提款)在另一列(您只需要一个正数或负数),
此外,CSV文件没有任何方式来指示它们使用的字符集编码,而且非常常见的是Excel(或使用Excel发送给您的人)产生的是一个(通常是Windows)编码,而您的消费者需要的是另一个(通常是UTF-8)。特别是像£这样的符号问题。
jcomma解决了这些问题,尤其是在您反复遇到相同布局的文件时。
使用方法
另请参阅安装。
(#husewebapp)
作为一个Web应用程序
填写表单并点击执行!。每次页面重新加载都会记住解释CSV文件的配方,您还可以从文件或浏览器存储中保存和恢复配方。
如果您提供了一个Web上配方的URL,jcomma将加载该配方而不是最近使用的配方。例如
https://jcomma.davidearl.uk/?recipe=https%3A%2F%2Fexample.com%2Fsome_recipe.json
这意味着您可以有效地共享配方。 (如果您将其放入Google Drive或Dropbox,我们将在您共享文件时将其转换为您可以直接下载的链接)。别忘了,当作为主URL的参数使用时,第二个URL必须进行百分编码(您可以通过在提供的框中加载它并然后复制URL来最容易地做到这一点)
(#huseapi)
通过API
要么
- 向/jcomma.php执行多部分编码的POST请求,提供CSV文件作为'csv'和配方作为'recipe',一个JSON字符串编码所有选项,如以下所示,作为一个POST参数;或者
- 执行POST(不需要多部分编码)带有上述'recipe'和'csvpaste'作为CSV数据的POST参数(当然,适当地编码)。
例如
curl -F "recipe=@recipe.json" -F "csv=@my.csv" "https://jcomma.davidearl.uk/jcomma.php"
您可以使用Web应用程序制作配方文件,保存它,然后程序化地使用它;或者即时制作一个。
(#huselibrary)
作为一个库
当使用composer安装时,使用库,包括vendor/autoload.php
,或者在其他情况下,在您的PHP应用程序中包含lib/JComma.php
,并像这样使用
$j = new \DavidEarl\JComma\JComma($pathtocsv, $recipeobject /* not JSON: already decoded */);
$errors = $j->validate(); // produces array of error message strings, or empty array if recipe is OK
if (empty($errors)) {
$result = $j->convert(); // produces array of objects
$j->output($result, $filename, $cl); /* optional: if you want to actually emit a file or string */
}
$recipe->outputTo 可以设置为 'string'(与通过API使用时不同),在转换为输出格式时返回字符串而不是输出到 stdout。$cl=TRUE ("命令行") 是可选的,并省略所有标题
(#huseshell)
在 shell 命令行
例如,像这样
php jcomma.php -s recipe.json my.csv
结果写入标准输出。recipe.json 是包含选项 JSON 表示的文件,如下所示。如果输入 csv 路径为 '-' 或省略,则从标准输入读取,因此可以在管道中使用该命令
echo my.csv | php jcomma.php -s recipe.json > my.xml
(#hloadrecipe)
加载配方
您可以通过在此处使用 选择文件 按钮打开 JSON 文件来加载页面底部链接中先前保存的配方(或在其他地方准备的)。在 Chrome 中,您只需将文件拖放到按钮上即可。
您还可以通过提供 URL 从云端加载配方。如果成功,URL 将包含在页面地址中,因此您可以分发该 URL 以共享 jcomma 中预先加载的配方。请注意,共享的 Google Drive 和 Dropbox URL 通常会带您进入下载页面,但 jcomma 会将其转换为可以直接从这些应用程序提供的共享 URL 加载。
或者,复制 JSON 并将其粘贴到提供的框中。
(#hresetrecipe)
重置配方
单击此按钮将页面重置为最简单的可能配方,然后您可以在此基础上扩展(这可能是必需的,因为页面会记住每次更改)。
(#hloadselect)
选择配方
当您为配方命名时,浏览器会自动使用该名称记住它,因此您可以通过从该菜单中选择名称来重新加载它。
(#hdeleterecipe)
删除配方
由于浏览器会分别保存所有命名配方,因此需要一种方法来清除它们。只需从菜单中加载相关配方,然后单击 删除链接。
(#hsaverecipe)
保存配方
表单中描述的所有设置都保存为 jcomma 配方、JSON 文件到本地文件。请注意,每次更改都会保存整个配方,因此如果重新加载页面,则更改不会丢失。
或者,复制提供的框中的 JSON 到您需要的地方,可选地通过勾选“美化布局”来美化布局。
除了 将其恢复到页面 之外,保存的配方还可以使用 jcomma 在自动化工作流程中使用,因此不需要手动在 JSON 中编写配方。
输出设置
(#hrecipename)
配方名称
您可以为配方命名,供您自己参考。命名配方由浏览器存储,因此可以按名称检索。
(#hcomment)
注释
这只是与配方一起保存,所以当您查看文件时,会有一些东西说明它是用于什么的。它只与 配方 一起保存,而不与输出一起保存。
(#houtputto)
输出到
选择是否将输出保存到下载的文件中或显示在浏览器选项卡中。请注意,csv 和 xlsx 文件始终下载(因为浏览器不知道如何处理它们)。
这对应于配方中的 "outputTo": "..."
,值 'inline'(用于显示)和 'attachment'(用于下载),以及用作库的 'string' 以将结果作为字符串检索。
(#houtputformat)
输出格式
jcomma 可以将其结果写入多种格式(例如 "outputFormat": "json"
在菜谱中)。其中一些格式有额外的选项
-
json:创建一个 JSON 对象数组,每个对象对应输入 CSV 中的每一行或一组行。(注意:JSON 默认以 UTF-8 编码)。
-
csv:输入 CSV 的转换。生成的每个记录形成一个行,每个生成的字段在该行中形成一个列单元格。
-
xlsx:Microsoft 的 Excel 2007 电子表格格式。这比 CSV 更好,因为字符编码定义良好,可以显式设置数据单元格的类型。它使用 PHP_XLSXWriter (感谢 mk-j;MIT 许可证)来创建文件。
- 包含标题行 (
"outputHeaderRow": true
在菜谱中):包含一个标题行,包括以下提供的字段名称
- 包含标题行 (
-
html:一个 HTML 表格,带有适当的周围 HTML 语法,形成一个完整的 HTML 页面
- 包含标题行 (
"outputHeaderRow": true
在菜谱中):包含一个标题行(在 HTML thead 元素中),包括以下提供的字段名称
- 包含标题行 (
-
xml:一个 XML 文件,有两种不同的布局。
-
将值作为元素而不是属性输出 (
"outputXMLElements": true
在菜谱中):当勾选时,每个生成的字段将输出为根据提供的字段名称命名的元素的 内容。当未勾选时,每个字段将作为容器记录的属性输出,属性名称来源于字段名称。 -
元素名称 (
"outputName": "name"
在菜谱中):记录元素的名称。所有这些元素都包含在一个由此名称加上 's' 命名的容器元素中。因此,如果输入的名称是 "person",我们将得到如下 XML 文件<persons> <person a="..." b="..." ... /> <person a="..." b="..." ... /> </persons>
-
-
qif:Quicken 互换单据格式。QIF 文件不允许使用任意字段名称,因此此也将下面的字段名称框更改为 QIF 文件中允许的选项菜单。
- 交易类型 (
"outputQIFType": "whatever"
在菜谱中):QIF 文件有一个标题,用于标识内容类型,例如 'Bank' 用于银行对账单行
- 交易类型 (
输入设置
(#hcsv)
CSV文件
选择要处理的CSV文件。在Chrome中,您可以直接将文件拖放到“选择文件”按钮上。以下内容描述了如何解释该CSV文件以将其转换为输出记录(然后根据所选的文件格式和选项进行格式化)。
(#hcsvpaste)
粘贴CSV
除了选择要处理的CSV文件外,您还可以将数据粘贴到提供的框中。当数据源是网页中的表格时,此功能非常有用,您可以直接复制并粘贴。在这种情况下,复制操作会在每个单元格之间放置制表符字符,而不是逗号,因此您还需要将分隔符字符设置为制表符。
(#hencoding)
输入CSV编码
CSV文件在处理基本ASCII字符集未表示的字符时完全模糊,例如重音字符、货币符号和异国标点符号,更不用说像日语和希伯来语这样的整个语言。虽然Excel在保存时确实有选择字符集的选项,但大多数人并不知道这一点,并且完全不知道后果,即CSV的消费者可能无法正确显示货币符号或非英语名称。通常,Excel使用特殊的Windows字符集导出CSV文件,而Google Sheets则使用名为UTF-8的标准国际字符集。
此选项(《编码》:“任意”》 在配方中)允许您明确指定CSV中期望的字符集(在设置为自动时,我们将尝试检测它,但并不总是能够正确检测)。
(#hheaderrows)
标题行
许多CSV文件都有标题行,用于标记列。一些CSV文件有额外的标题行,人们可以将任意数据放入其中(例如,银行对账单CSV文件可能会使用一行来表示账户号码,另一行来表示账号)。
在此处指定CSV中的标题行数(例如 "headerRows": 1
在配方中)。0表示没有标题行,而1是最常见的。
如果标题行数为1或更多,则最后一个标题行假定包含列标题,可以使用这些标题或与列字母一起识别列。这可以使设置更容易遵循。列标题和字母不区分大小写。此外,请注意,传统上第27列及其之后的列是“AA”、“AB”、“AC”等,第53列是“BA”、“BB”、“BC”等,类似于Excel。
(#hrowcount)
由...行形成的每条记录
当处理CSV文件时,通常每行用于创建一条(有时是多条)输出记录。但是,有时一条记录可能由多行组成,如果数据分布在多个行中。
此数字(《rowCount”:1》例如 在配方中)表示构建每个记录(或记录组)需要消费多少行(在丢弃以下任何忽略的行之后)。1是典型值。
(#hdelimiter)
分隔符
期望CSV中的列由此字符(例如 "delimiterChar": ","
在配方中)分隔,通常是逗号。如果您有以制表符分隔的列(也称为TSV文件),请勾选“制表符”框(因为无法轻松输入制表符字符)。
将HTML表格直接复制粘贴为纯文本时,通常是使用制表符分隔的,所以如果你从网页上复制一个表格并将其粘贴到粘贴CSV框中,将分隔符设置为制表符,应该可以在不先将数据保存到电子表格的情况下处理数据。
(#henclosure)
包围字符
在CSV文件中,大部分列数据都是直接列出,但需要包含分隔符字符(例如逗号)的列需要被一对这些字符包围(例如,"enclosureChar": "\""
,如在食谱中所示),通常是双引号。此设置允许你更改该字符 - 如果文件使用单引号,例如。
如果包围的字段也包含包围字符,则需要将其加倍。例如,使用传统的双引号,我们可能会有:
...,"This field has a "" symbol",...
或者如果分隔符是斜杠字符并且需要包含一个单斜杠:
...,/This field has a // symbol/,...
(#hignorerows)
忽略行...
人们经常在CSV文件中间放置随机行,这使得它们特别难以有顺序地处理。例如,银行经常在每个“页面”重复其标题行,无论这意味着什么。
此设置("ignoreRows": [ ... ]
在食谱中)允许你根据一个或多个标准忽略此类行。通过按+按钮添加新标准,通过X移除现有标准,并拖动↕来更改顺序。如果满足任何标准,则忽略该行。
你可以根据传入CSV中指定列的单元格值(提供其名称,可以是列字母或列标题)或根据从传入CSV计算的字段之一(提供其名称以匹配你下面指定的名称)来忽略行。
有关条件(在多个不同位置使用相同的一组条件)的详细信息,请参阅条件。
请注意,在提取任何标题行(从CSV中精确消耗给定数量的行)时,不会以这种方式忽略行。
(#hconcatrows)
合并行...
虽然你可以读取多行以获取所有内容,但有时CSV文件会突然出现额外的意外行。你可以根据某些条件(例如,第一列是空的)有选择性地合并行。
此设置("combineRows": [ ... ]
在食谱中)允许你根据一个或多个标准将此类行一起包含。通过按+按钮添加新标准,通过X移除现有标准,并拖动↕来更改顺序。如果满足任何标准,则将行与上一行合并。
有关条件(在多个不同位置使用相同的一组条件)的详细信息,请参阅条件。
请注意,在提取任何标题行时,不会以这种方式合并行(从CSV中精确消耗给定数量的行)。
注意,直到某个行不满足条件,行将继续合并,如果每个记录通常由多行组成,则这将继续适用于后续未合并的行。
(#hrecords)
输出记录
通常,你会为每个输入行(根据忽略行不是被忽略的)或根据'每个记录由...'的给定行数产生一个输出记录。然而,偶尔为每行制作多个记录可能是有帮助的。每个此类记录将连续出现在输出中,例如作为JSON数组中的对象或输出CSV中的额外行。
例如,您可能从PayPal交易中产生两个记录,其中一个记录表示支付(贷记),另一个记录表示PayPal费用(PayPal将其放在其导出中的同一行),作为另一个记录(借记:银行费用)。
因此,这里的+允许您添加一个或多个要生成的记录的配方,尽管您通常只需要一个。("records": [...]
在配方中)。点击X删除一个,拖动↕更改顺序
每个记录由一系列字段和一个基于这些字段的条件集组成,该条件集在记录将被丢弃时适用。
(#hfields)
输出记录的字段
记录的每个字段("fields": [...]
在配方中)包含一个名称、一个或多个列和一些字面文本,这些文本是构成其初始值的来源,以及一系列依次应用的可转换、省略或拒绝值的选项。
使用+添加新字段,使用X删除现有字段,并拖动↕更改顺序
字段按在输出记录中指定的顺序交付。
(#hname)
字段名称
字段名称("name": " whatever"
在配方中)用于输出,例如作为JSON中的对象成员名称,作为XML中的元素名称或CSV、HTML和XLSX中的列标题。
如果名称包含点和/或方括号中的整数,则将为支持层次化输出的这些格式构建从属对象和数组。例如,我们可能会有名为“salutation”、“address.city”和“address.postcode”的输出字段。在JSON输出中,它们将显示为
[
{
"salutation": "Miss Doe",
"address": {
"city": "Lerwick",
"postcode": "ZE1 1AA"
}
},
...
]
在XML(元素名为“person”)中,例如
<persons>
<person>
<salutation>Miss Doe</salutation>
<address>
<city>Lerwick</city>
<postcode>ZE1 1AA</postcode>
</address>
</person>
</persons>
同样,字段名称“people[0].name”可能产生
[
{
"people": [
{
"name": "Jane Doe"
}
]
},
...
]
这样,电子表格的多个列可以分散为输出中的数组元素。目前无法包含任意数量的数组元素。
在表格格式(HTML、CSV、XLSX)中,值只是作为连续的列出现,当请求时,这些列以点/索引名称为标题。列标题是从第一条记录的字段名称计算出来的。
您可以使用多个具有相同名称的字段(通常是连续的),只要您设置选项以在相反的情况下省略每个字段。例如,如果您在原始CSV中有借记和贷记列,但需要单个简单的数字,贷记为正数,借记为负数。因此,您可以创建一个来自贷记和同一字段来自借记的字段,每个字段都有省略为零的选项,并将其转换为数字,而借记版本的字段还包括在转换为数字时进行取反的选项。(然而,如果相反的列实际上总是空白的,而不是零 - 更常见的情况 - 创建一个包含两个列的单个字段会更容易,并设置选项在连接中将借记列前缀为减号)。
不包括在输出中
("exclude": true
在配方中) 完全从输出中排除字段。这与“省略”条件不同,因为字段直到输出才会保留在输出记录中,因此可以引用其他字段。因此,它有点像变量。
(#hcomprising)
从以下内容拼接字段
在应用任何选项之前,将几个列通过字面分隔符交错连接,以形成一个输出字段。例如,一些银行提供几个字段,可以将它们有用地放入单个描述字段中。您几乎总是需要至少一个列。("comprising": [{"item": "column", "column": "A", ...}, ...]
在配方中)
当存在多于一行输入时(rowCount 大于 1),您需要说明 CSV 单元格是从哪一行获取的(这也允许您从同一列垂直连接几个值),通过给出行偏移量(第一行偏移量为 0,每组的第二行偏移量为 1,依此类推)。
您还可以包含
-
文本,例如用于括号化第二列。(例如:
"comprising": [{"item": "text", "text": " whatever text"}, ...]
在食谱中)。 -
另一个字段作为该字段的来源。然而,它必须是记录中定义早的字段:字段按顺序计算,所以在此点之后不可用。(
"comprising": [{"item": "field", "field": "name", ...}, ...]
在食谱中)。 -
从上一行而不是正在处理的当前行获取列的值。
-
从之前输出的记录中的字段值。
对于字段和列,可用的复选框有
- 在包含之前从列中删除任何前导或尾随空白(空格、换行符、制表符)(
"trimSpaces": true
在食谱中), - 当输入非空时(在裁剪后),前缀一个负号(
"prefixMinus": true
在食谱中)。将负号前缀到一对连接列中的一列提供了一种方法,将单独的贷方和借方列(当其中之一始终为空时)转换为单个正/负列(如果需要,可以在输出选项中稍后删除货币符号)。 - 当输入非空时(在裁剪后)附加一个逗号(
"appendComma": true
在食谱中), 从而将输入列形成逗号分隔列表,并且 - 当输入非空时(在裁剪后)附加一个空格(
"appendSpace": true
在食谱中)
以任何组合方式。这只是一个将这些作为纯文本包含的快捷方式。
点击 + 以包含新列、字段或文本,X 以删除一个,并拖动 ↕ 以更改顺序
(#hoptions)
字段选项
通过从 CSV 中的一个或多个单元格中通过连接生成字段值后,可以使用字段选项以各种方式转换该值。可以应用多个选项,按给出的顺序。点击 + 添加新选项,X 删除现有选项,并拖动 ↕ 以更改顺序。
可用的选项如下
-
忽略货币符号... (
"item": "ignoreCurrency", "currencies": "..."
在食谱中):从字段值中移除列表中提供的任何货币符号(或任何其他单个字符),无论它们出现在字符串的何处。示例:如果货币列表仅为 "£",并且当前值是 "£123.45",则结果将是 "123.45"。但是,如果列表为 "°"(度符号)且值为 "90°",则此选项也可以用来移除它,得到 "90"。 -
将 '(1.23)' 或 '1.23-' 视为负... (
"item": "bookkeepersNegative"
在食谱中):账目有时通过括号(这使得它们更明显,但难以处理)或甚至有时通过尾随而不是前导的负号或加号来表示负数。使用此选项将这些转换为正确的负数。请注意,您最终仍是一个字符串,并可能还需要将其转换为数字(如下所示)。示例:"(123.45)" → "-123.45";"123.45-" → "-123.45"。 -
去除周围的空白 (
"item": "trim"
在菜谱中): 从值中删除所有前导和尾随空格、换行符、制表符以及任意组合中的任何数字。例如:" 123.45 " → "123.45" -
替换所有字符串出现 (
"item": "replaceString", "matches": "string", "output": "replacement"
在菜谱中): 用其替换替换替换给定的字符串在值中的所有出现。例如,如果值是 "the cats scattered",匹配是 "cat",替换是 "dog",结果是 "the dogs sdogtered"! -
使用正则表达式替换 (
"item": "transform", "matches": "regexp", "output": "replacement"
在菜谱中): 如果字段与提供的 正则表达式 匹配,则替换为提供的替换。可以使用 $1、$2 等,用于正则表达式中括号内的元素进行替换。例如:如果值是 "the cat sat on the mat",正则表达式 "/ c?t /" 和替换 " dog ",我们将得到 "the dog sat on the mat"。 -
输出为数字 (
"item": "convertToNumber", "errorOnType": true, "negate": true
在菜谱中): 将值转换为输出中的数字,以便可以在输出中进行算术运算,例如(它也适用于后续测试中的更大和更小选项)。如果字符串值无法转换(例如 "12a"),则如果勾选了 停止转换 复选框,整个 CSV 转换将停止并显示适当的错误消息,否则则输出为 0(零)。如果勾选了 转换后取反 复选框,则结果是转换后的数字的相反数。例如,银行对账单的借方列可能需要产生单元格内容的相反数,如果与贷方列合并。请注意,如果字段由某些列与先前记录中相应字段连接而成,您可以从多行中汇总列。 -
输出为数字之和 (
"item": "convertToNumberSum", "errorOnType": true, "negate": true
在菜谱中): 将值转换为输出中的数字,该数字由字段中的多个数字之和形成。例如,该字段可能是您希望相加的两个输入数字列的空格分隔连接。总和的数字可以用任何组合的空格和逗号分隔。然后您可以在输出中进行算术运算,例如(它也适用于后续测试中的更大和更小选项)。如果字符串值无法转换(例如 "123 12a"),则如果勾选了 停止转换 复选框,整个 CSV 转换将停止并显示适当的错误消息,否则则不包括在总和中。如果勾选了 转换后取反 复选框,则结果是结果数字的相反数。 -
输出为ISO日期 (
"item": "convertToDate", "errorOnType": true, "dateFormatUS": true, "dateFormatTime": true
在配方中): 将值转换为标准日期,无论其原始形式如何。输出格式由国际标准 ISO 8601 确定,如 "2016-12-02" 或 "2016-12-02T13:36:45+00:00"(如果包含时间)。许多系统都认识这种格式,它既易于排序又无歧义。转换使用Linux strtotime 函数,因此它理解多种可能的值。然而,使用斜杠表示的欧洲和美国日期(如 "3/4/2016")是模糊的(欧洲是 d/m/y 因此是 3 月 4 日,而美国是 m/d/y,因此是 3 月 4 日),所以 美国日期 复选框允许您指明CSV包含的是哪个(如果选中则是美国)。(它通过在呈现给 strtotime 之前将斜杠替换为短横线来实现这一点)。如果值不是可理解的日期,那么如果 停止转换 复选框被选中,则整个CSV转换会停止,否则会以空字符串输出。 -
输出为自定义日期 (
"item": "convertToCustomDate", "errorOnType": true, "dateFormatUS": true, "dateFormatStyle": "j M Y"
在配方中): 与ISO日期类似,但您可以自己指定输出样式(包括时间部分)。它使用 PHP date函数,其中日期样式中的字母被日期或时间的部分所替换。例如 "M j, Y" 产生日期 "Dec 1, 2016",因为 M 代表缩写月份名称,j 代表不带前导零的日期,Y 代表四位数年份。还有许多其他可能的变体 - 请参阅 date。 -
如果...则省略字段 (
"item": "omitIf", "condition": "...", ...
在配方中): 通过其他任何方法转换字段后,如果选定的 条件 满足,则丢弃该字段。省略字段在JSON和XML格式中可能很有用,但在表格格式(CSV、HTML、XLSX)中,这会导致列向左移动一位,因此最好在上面的转换中将其转换为空字符串值。请注意,当省略字段时,不会对该字段应用其他选项,并且该字段对于后续字段不可用,例如比较等。 -
如果...则从上一条记录继承 (
"item": "carryOverIf", "condition": "...", ...
在配方中): 如果选定的 条件 满足,则完全丢弃之前通过选项连接和转换的值,并替换为上一条相应记录中同一字段的值(无论该记录是否实际输出)。结合是否输出记录的条件,这可以用来将不同行中的值合并为单个记录。 -
如果...则跳过下一个选项 和 如果不...则跳过下一个选项 (
"item": "skipIf", "condition": "...", ...
或"item": "Unless", "condition": "...", ...
在配方中): 根据此 条件 的结果,可以应用或跳过下一个选项。 -
如果值错误则停止... (
"item": "errorOnValue", "condition": "...", ...
在配方中): 通过任何其他方法转换字段后,如果此处选择的 条件 满足,则整个转换过程可以终止:例如,如果遇到意外值。
每个条件选项(跳过、省略和停止)都可以将给定的值与以下任何一项进行比较
- 从先前的步骤中计算的字段当前值(《code>"test": "value"
在配方中),
- 列的值(《code>"test": "column", "column": "header"
在配方中)
- 任何先前字段的值(《code>"test": "field", "field": "name"
在配方中)
(#hunless)
不输出记录...
计算了一个记录的所有字段后,可以使用计算出的值来确定,如果满足以下 条件 中的任何一个,则其记录根本不应包含在输出中。按 + 添加新条件,按 X 删除现有条件,并拖动 ↕ 以更改顺序。
在多个位置使用的设置
(#hconditions)
条件
- 为空(没有任何文本) (
"condition": "empty"
在配方中): 值中没有任何内容,甚至没有空格,或者对于字段,该字段不存在或为空字符串。
- 仅空白或为空 (
"condition": "white"
在配方中): 如果值是空的,如上所述,或者只包含空格、制表符、换行符或换行符字符,以任何组合。
- 匹配正则表达式 (
"condition": "match", "value": "regexp"
在配方中): 如果值匹配提供的正则表达式。请参阅 正则表达式
- 不匹配正则表达式 (
"condition": "nomatch", "value": "regexp"
在配方中): 如果值不匹配提供的 正则表达式
- 等于 (
"condition": "eq", "value": " whatever"
在配方中): 如果值与给定值相同。输入单元格和输出字段作为字符串进行比较,但转换为数字的字段与给定值进行数值比较,因此在使用涉及数字的输出字段时,最好使用此条件。
- 不等于 (
"condition": "ne", "value": " whatever"
在配方中): 如果值与给定值不同。比较方式与“等于”相同。
- 大于或等于 (
"condition": "ge", "value": 123
在配方中): 值大于等于给定值,这只有对数字才有意义,因此如果需要,首先将输入和输出值转换为数字,然后进行比较。 - 小于或等于 (
"condition": "le", "value": 123
在配方中): <= - 数值,与“大于或等于”相同。 - 之前(日期) (
"condition": "before", "value": "2016-09-23"
在食谱中): 日期比较 - 输入的日期和比较的日期都不能包含 '/',即不能有歧义。在字段的情况下,您可以在比较后始终将其转换为 ISO 格式,然后再转换为另一种格式,但忽略行仅适用于非歧义日期。 - 之后(日期) (
"condition": "after", "value": "2016-09-23"
在食谱中): 日期比较,与“之前”相同。 - 等于上一行的列 (
"condition": "eqprev", "prevcolumn": "letter/header"
): 如果比较的值等于上一行中通过其列字母或标题标识的列,则满足条件。 - 不等于上一行的列 (
"condition": "neprev", "prevcolumn": "letter/header"
): 如果比较的值与上一行中通过其列字母或标题标识的列不同,则满足条件。
(#hregularexpression)
正则表达式
正则表达式是一种用于表达文本字符串语法的语言。jcomma 使用所谓的 PCRE 正则表达式,如 PHP 中所示。正则表达式必须包含分隔符(任何合适的字符对)和任何尾随修饰符。
有关正则表达式语法的完整详细信息,请参阅 PHP 手册。
例如,以下将匹配仅由字母 A、B、C 或 a、b、c 组成的字符串(使用波浪线作为分隔符,尾随修饰符 'i' 表示不区分大小写,^ 和 $ 要求字符串的开始和结束,方括号表示字符范围)
~^[a-c]$~i
请注意,当您需要转义一个字符时,在 PHP 字符串中您经常发现您需要两个反斜杠,一个用于 PHP 的字面字符串语法,另一个用于正则表达式本身。在这里,这些不是 PHP 字面字符串,所以只需要一个。
如果提供了替换,可以使用 $1、$2 等,就像在 PHP 中一样,来替换括号匹配的内容。
(#hrecipe)
JSON 食谱(“食谱”)
表单中输入的值被转换为 JSON 对象。这可以 保存到文件。
当从 API 使用、作为 库 使用或在 shell 命令 中使用时,食谱以这种结构化形式提供。(是的,我知道 JSON 真的不能有这种注释)。
{
"recipeVersion": 3, # always this for these options
"outputFormat": "json", # csv, html, xlsx, xml
"outputStyle": "pretty", # for json
"outputBulkElastic": "true", # for json, any non empty value
"outputName": "whatever", # filename, also used to name elements where needed by format
"outputTo": "inline", # or "attachment", or when used as a library, "string"
"outputEncoding": "UTF-8", # or "Windows-1251". For CSV files only (the others are fixed by the file format)
"outXMLElements": "true", # <x><k>v</k>...</x> rather than <x k="v" ...></x>
"encoding": "UTF-8",
"headerRows": 8,
"delimiterChar": ",",
"enclosureChar": "\"",
"rowCount": 1, # default 1
"ignoreRows": [ # one or more of these (row ignored if any is true):
{"item": "column", "name": "A", "condition": "...", "value": "..."}, # conditions as before
{"item": "field", "name": "name", "condition": "...", "value": "..."},
...
],
"records": [
{
"fields": [
{ "name": "...",
"comprising": [
{"item": "column",
"column": "A",
"rowOffset": 0, # optional, N=0 by default, otherwise from row relative to current from the N specified for the record in rowCount
"trimSpaces": true, # applied first if set
"prefixMinus": true,
"appendComma": true,
"appendSpace": true # comma first if appendComma also set
},
{"item": "text",
"text": "whatever"
},
{"item": "field",
"field": "name",
"trimSpaces": true, # applied first if set
"prefixMinus": true,
"appendComma": true,
"appendSpace": true # comma first if appendComma also set
},
...
],
"options": [ # any of the following, evaluated in turn:
{"item": "ignoreCurrency", "currencies": "pound-sign etc"},
{"item": "bookkeepersNegative"}, # (123) or 123- => -123
{"item": "trim"}, # trim surrounding white space
{"item": "replaceString", "matches": "string", "output": "substitution"},
{"item": "replaceRegExp", "matches": "regexp", "output": "stringwithdollarsubstitutions"},
{"item": "convertToNumber", "errorOnType": true, "negate": true}, # any non blank value ok for options
{"item": "convertToDate", "errorOnType": true, "dateFormatUS": true, "dateFormatTime": true},
{"item": "convertToCustomDate", "errorOnType": true, "dateFormatUS": true, "dateFormatStyle": "j M Y"}, # per PHP date function
{"item": "omitIf", "test": "value", "condition": "match", "value": "..."},
{"item": "omitIf", "test": "field", "field": "name", "condition": "match", "value": "..."},
{"item": "skipIf", "test": "value", "condition": "match", "value": "..."},
{"item": "skipIf", "test": "field", "field": "name", "condition": "match", "value": "..."},
{"item": "skipUnless", "test": "value", "condition": "match", "value": "..."},
{"item": "skipUnless", "test": "field", "field": "name", "condition": "match", "value": "..."},
{"item": "errorOnValue", "test": "value", "condition": "match", "value": "..."} # match, eq etc, blank, white, nonNumeric
{"item": "errorOnValue", "test": "field", "field": "name", "condition": "match", "value": "..."} # match, eq etc, blank, white, nonNumeric
]
} ,
... # more fields
],
"unless": [ # generate record from row unless any condition is true
{ "field": "name", "condition": "eq", "value": "..."},
... # more 'unless' conditions, record discarded if any is true
]
},
... # more records (occasionally)
]
}
(#hinstallation)
安装
需要 PHP >= 5.4。不支持旧浏览器(它使用的是 jQuery 的最新版本)。它可能在 PHP 5.3 上运行,但 JSON Pretty Print 可能会在服务器错误日志中产生警告。
将文件放在您的 Web 服务器文档根目录中,理想情况下是一个 https 网站,或者作为网站的子目录。
转到顶级目录并运行 composer 生成自动加载并安装依赖项
composer update
如果您不能使用 composer,请在您的项目中包含 lib/JComma.php
。您将需要 composer 来创建网站。
您可能需要从 PHP 默认设置中增加服务器设置中的单个文件和总文件上传限制。
致谢
除了 PHP 和服务器软件之外,唯一依赖项是
- PHP_XLSXWriter 用于 xlsx 文件格式输出,许可协议为 MIT,以及
- jQuery 和 jQuery UI,也是 MIT 许可协议。