daVidearl/jcomma

将CSV文件转换为一致的格式

v7.2.1 2024-04-08 10:57 UTC

This package is auto-updated.

Last update: 2024-09-08 11:48:26 UTC


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 编码)。

    • 美化打印 ("outputStyle": "pretty" 在菜谱中):以更易读的布局展示 JSON 输出,而不是全部放在一行中
    • 用于 Elasticsearch 的批量数据:("outputBulkElastic": true 在菜谱中):不是数组,而是为每条记录创建一行,交替着 JSON 对象,以控制 Elasticsearch 使用其 批量 API 创建 Elasticsearch 文档。如果提供了类型名称字段,则每个记录的类型将填写到该字段中("outputName": "name" 在菜谱中),如果没有,则填写输入文件(去除后缀)的名称。(注意:在这种情况下忽略美化打印)
  • csv:输入 CSV 的转换。生成的每个记录形成一个行,每个生成的字段在该行中形成一个列单元格。

    • 输出编码 ("outputEncoding": "whatever" 在菜谱中):输出 CSV 的字符编码。
    • 包含标题行 ("outputHeaderRow": true 在菜谱中):包含一个标题行,包括以下提供的字段名称
  • 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 和服务器软件之外,唯一依赖项是