使用 Envision 读取表格文件


首页 » 资源 » 此处

Envision 可以加载您的 Lokad 账户中存储的表格文件并进行处理。此外,Lokad 还为各种第三方应用提供本地支持。如果您的应用受 Lokad 支持,导入数据和创建必要文件的过程将全部由我们内部进行管理。但如果此举不可行,或者Lokad 无法检索所有相关数据,那么可能需要手动导入文件到 Lokad。本页详细说明了如何将表格文件格式化为与 Envision 兼容的格式。下文还介绍了与系统读取表格文件有关的 Envision 语法。


简介

Lokad 支持的文件格式有:

  • CSV、TSV 以及其他类似的常用平面文本文件,.csv.tsv.txt 文件。
  • Microsoft Excel 2007+ 文件, .xlsx 文件。
  • GZip 存档,.gz 文件;内容应为平面文件。
  • WinZip 存档,.zip 文件;内容应为平面文件;存档只能包含 1 个文件。
  • 7z 存档,.7z 文件;内容应为平面文件;存档只能包含 1 个文件。

在 Envision 中读取文件的语法为:
read "/foo/myorders.csv.gz" as Orders with "My Id" as Id, Quantity : number
read "/foo/promos*.xlsx" as Promos[*] // wildcard '*' here, multiple files will be read
read max "/foo/stocks*.xlsx" as Stocks[*] // max within the wildcard '*', only one file is read
read "/foo/backorders.tsv.zip" unsafe as Backorders[Date, *] // 'unsafe' tolerate parsing issues

附带连接器的自动存储

每个 Lokad 账户都自带文件存储服务。您只需要创建文件夹,并将文件上载至这些文件夹。在这方面,Lokad 所提供的服务类似于 Box 或 Dropbox 等其他文件托管服务,但 Lokad 不提供大部分文件共享功能。实际上,Lokad 文件存储系统的意图并非成为另一款文件共享应用,而是在进行商业分析时提供一种完全透明的途径,来访问 Lokad 使用的所有数据。因此,只要 Lokad 生成预测或仪表盘,便会下载您的账户中以文件格式存在的相应数据,并独立于 Lokad 来进行分析。

对于小型企业,建立用于收集公司所有相关历史数据的文件是一项单调沉闷的工作,因为此类企业并非总是将重要的 IT 资源摆在首位。因此,对于许多常用的商业应用,例如 Brightpearl、Linnworks、QuickBooks、TradeGecko、Unleashed、Vend 等等,Lokad 提供内置连接器。这些连接器通常也可以运用在线 API(应用程序编程接口)连接应用,并在 Lokad 账户中直接格式化然后生成最适合通过 Envision 处理的文件。

如果您的商业应用不受支持(如果发生这种情况,请,我们很愿意为最常用的应用提供支持),或者如果 Lokad 的内置支持无法处理所有相关数据,在此情况下,可以直接将文件上载至 Lokad,因为我们支持通过 Web 进行手动上载。但鉴于数据会定期刷新,以全自动化的方式进行数据传输会更实用。因此,Lokad 还支持 FTP 和 SFTP 等具备自动传输所有文件功能的协议。

广泛支持表格文件

Lokad 支持相当广泛的可以包含表格数据的文件。我们支持常用的格式,例如 Excel 工作表或 CSV(逗号分隔值)文件。如果您是进行平面文件导入/导出,您可能已经知道这里面涉及到无数的技术细节,会让整个过程变得无比单调沉闷:

  • 文件编码可能与应用预期的编码不同。
  • 日期或数字可能无法按预期的格式化。
  • 列分隔符或行回车编码可能也不同。

我们的系统设计,决定了我们能够自动检测所有技术细节,例如编码、日期和数据格式、分隔符等等。在系统读取文件时,一切操作自动进行,这在 Lokad 中是一个相当不寻常的过程。例如,我们现在支持自动检测超过 100 种不同的日期格式。

实际上,表格文件格式的原则非常简单:列名作为文件的第一行(此要求也适用于 Excel 工作表),并且在使用 CSV 或 TSV 等平面文本文件时,必须确保标记值与分隔符不冲突。

此外,随着平面文件不断增大,在上载至 Lokad 之前进行压缩更实用。Lokad 支持使用 GZip 压缩平面文本文件 ,前提是在文件名末添加 .gz 扩展名。例如,Lokad_Items.tsv.gz 被识别为使用 GZip 进行了压缩的 TSV 文件。对于扩展名为 .zip 的 WinZip 存档,以及扩展名为 .7z 的 7z 存档,情况同样如此。对于 WinZip 和 7z,此类存档只能包含一个压缩文件;Envision 不支持包含多文件的存档。Excel 工作表也进行了压缩,因此如果文件很大,无需进行压缩。

文件和列的命名原则

Lokad 几乎支持使用任意文件名和任意列名,但如果遵循特定的原则,会让 Envision 脚本变得更简单。样本数据集便是一组文件遵循这些原则的好例子。如果您迄今尚未查看过该数据集,建议您现在就去看一下。

文件应按 Lokad_TableName.xyz 这种模式命名,其中 TableName 替换为表名,xyz 替换为实际文件扩展名,例如 Excel 工作表的扩展名为 xlsx。表名不能包含任何空格,也不能以数字开头。通过遵循这些文件命名约定,Envision 无需进行进一步的操作,便能自动检测要上载到 Lokad 中的相关表。

在该表中,每段 Envision 脚本均应上载一个项目表到系统中。因此,应通过某种方式向 Lokad 提供名称为 Lokad_Items.xyz 的文件。尽管并无严格要求,但 Lokad_Orders.xyz(销售历史记录)和 Lokad_PurchaseOrders.xyz(供应商采购历史记录)也是本应用通常所需的文件。 具体而言,项目表属于一种特殊情况,对于许多 Envision 脚本来说,围绕这样一个项目表来组织数据是很有好处的。但是,项目表并非必须提供,在不加载此类表的情况下 Envision 同样能够运行。但如果向 Envision 提供了名称为 Lokad_Items.xyz 的文件,则此文件会默认作为项目表来处理。

如果一个表被分割成多个文件(例如由于单个文件太大),Envision 可将所有文件整合成一个表。要做到这一点,所有文件应命名为 Lokad_TableName_Suffix.xyz,其中 Suffix 视文件而有所不同。例如,如果针对销售摘要建立了每日摘要,那么其中一个每日销售摘要应命名为 Lokad_Orders_2015-03-16.tsvSuffix 并无特殊作用,仅用于体现文件的不同,因此可以为任何内容。当然,Envision 将在所有仅后缀不同的文件中查找相同的列,否则无法在未提供其他说明的情况下将这些文件整合为一个表。

Envision对列名并无特别要求。另外 Envision 也具有一些默认的行为:
  • 在平面文件中可以找到名称为 Id 的列,默认情况下,该列作为 Lokad_Items.xyz 文件中最初找到的 Id 列的外部键来处理。
  • 列的名称末尾为 Date 时,默认情况下,该列被 Envision 作为日期处理。

大部分列名都是可以接受的,只要其中不包含空格或不以数字开头。此外 Envision 也提供了多种覆盖上述行为的途径。但是,建议您尽量遵循这些原则,因为这样可以减少在 Envision 中获取结果的脚本开销。

用于读取文件的语法

Envision 支持一种丰富的文件读取语法,它能够处理无法遵循我们的命名指南时的情况(例如文件无法进行内部修改时)。下面概述了该语法:目前尚不是完全通用的语法,下面将详细介绍其他一些选项。
read "/foo/bar*.xyz" as MyTable with "Foo1" as Id, "Foo2" as Date, "Foo 3" as Foo3
/foo/bar*.xyz 路径可以包含通配符 (*),该通配符可替换为任意字符序列。通配符可以选用,但如果使用通配符,可以一次捕捉多个文件。在通过命令行列出文件时,这种模式类似于 shell 语法。

位于路径右边的第一个关键字是 as,用于指示表名。举个例子,如果表名为 MyTable,Envision 脚本将编写 MyTable.Id 来引用此表。如果要加载的是项目表本身,则 as MyTable 会被跳过。

紧随关键字 with 之后的说明作为列重命名的说明。在上例中,列 Foo1 被重命名为 Id,列 Foo2 被重命名为 Date。通过对这两列进行重命名,表 MyTable 成为一个合法的包含历史数据的 Envision 表,因为现在 IdDate 这两列进行了正确的定义。

第三项重命名操作是将 Foo 3(注意初始列名中的空格)重命名为 Foo3。这项操作诠释了如何将不正确的列名转换为正确的列名。此外还要注意,向量变量名也不允许包含空格。为求简洁,我们没有再列举其他重命名对,但实际上,只要这些对用逗号正确分隔,一个文件中可以进行的重命名操作次数就不受限制。重命名列对于提高脚本的可读性很有用,并且在需要将多个文件整合成一个表,但这些文件的列名不一致的情况下,也可以通过这种方法来进行所需的调整。

举个比方,假设订单历史记录被分割为两个文件。首先是 Lokad_Orders_Old.tsv,它包含截至 2014 年 12 月 31 日的所有数据。此文件有三列,分别为 ItemIdOrderDateQuantity。该文件的列并未遵循 Envision 的列命名原则。再者是 Lokad_Orders.tsv,这个文件较新,包含从 2015 年 1 月 1 日起的所有历史数据。这个文件也有三列,分别是 IdDateQuantity,列名遵循 Envision 的默认原则。以下脚本诠释了这两个文件整合成一个 Orders 表的过程。
read "/foo/Lokad_Orders_Old.tsv" as Orders with "ItemId" as "Id", "OrderDate" as Date
read "/foo/Lokad_Orders.tsv" as Orders
当然,您也可以定义多条 read 语句以便充分涵盖所有文件和所有表。Envision 对于这些语句在脚本的位置并无硬性规定,所以严格来说,这些语句可以放在任意位置,即便放在脚本最后也可以。但是,我们建议将这些语句放在脚本开头,因为熟悉编程语言的人通常希望在开头位置可以找到这些语句。

通配符过滤器

通配符 (*) 提供了选择多个文件的能力;但是,有时通配符的意图是只读取其中的一个文件。如果其意图是在根据文件名对文件进行排序时只读取"最后"一个文件,那么这个过程可以这样完成:
read max "/foo/bar*.xyz" as MyTable with "Foo1" as Id, "Foo2" as Date, "Foo 3" as Foo3

通配符过滤器有三种:

  • min:根据各自的文件名对文件排序时,读取第一个文件(按字母顺序)。
  • max:根据各自的文件名对文件排序时,读取最后一个文件(按字母顺序)。
  • latest:根据上次修改日期对文件排序时,读取最后一个文件。

举个例子,如果库存水平的快照每天推送到 Lokad,快照文件名为 stocks-2016-12-21.csv,即后缀进行了调整以反映当前日期,那么很有可能其意图是只读最新的文件。在这个具体的例子中,maxlatest 会产生相同的结果,因为文件命名惯例与更新日期保持一致。

定义类型预期

除非另有规定,否则 Envision 将预期任何表(Items 表除外)都包含 Id 列和 Date 列。如上节所述,通过重命名相关列可获取这两列。但是,有时一个表可能并不与预期相符,那么就可以使用 Envision 语法来阐明与表相关的预期。同样,一般从 Envision脚本本身可以推断出列类型,但有时单纯依靠类型推断并不够。这时,同样可以使用 Envision 语法来指定所需的列类型。

Envision 提供了定义表的主键的功能,方法就是在定义后面的圆括号中列出这些主键。只允许以下 7 种主键组合:
read "a.csv" as A[*]
read "b.csv" as B[Id]
read "c.csv" as C[Id, *]
read "d.csv" as D[Date]
read "e.csv" as E[Date, *]
read "f.csv" as F[Id, Date]
read "g.csv" as G[Id, Date, *]
案例 A[*] 定义的表无任何限制。它是一个通配符,可以适应截然不同的情况,但如果没有 Id 列,就会失去 Envision 语言的一些精妙之处。

案例 B[Id] 定义的表每个项目最多允许一行。例如,库存设置属于此类。

案例 C[Id, *] 定义的表每个项目可允许任意行。例如,用于表示概率分布的表就属于这一类。

案例 D[Date] 定义的表包含特定天数内的单一标量值。例如,此类表可用于列出适用于特定地理位置的国家法定假日。

案例 E[Date, *] 定义的表包含特定天数内任意数量的标量值。它是上一个案例的扩展,其中指定的某天可以关联多个因素。

案例 F[Id, Date] 定义的表中每对 [Id, Date] 最多包含一个值。例如,此类表可用于列出过去发生的缺货次数。

案例 G[Id, Date, *] 为默认行为,即忽略圆括号时发生的行为。实际上,大部分历史数据都属此类,例如销售订单历史记录。

表列的类型限制

Envision 是一门强类型语言。所有向量都与 Envision 中可用的某种类型相关联。Envision 中只能使用 4 种类型:文本数字日期布尔值,这些类型通常都可以从脚本本身直接推断出来。但也可以使用下面的语法指定预期的类型:
read "a.csv" as A[*] with "Foo" as X : text, Y : number, Z : date
再回到样本数据集,如果编写以下语句:
read "/sample/Lokad_Items.tsv"
read "/sample/Lokad_Orders.tsv" as Orders
read "/sample/Lokad_PurchaseOrders.tsv" as PO
//the three lines above will be omitted in the following
Quantity = sum(Orders.Quantity)
那么,向量 Orders.Quantity 将作为数字隐式输入,因为只有数字才可以求和。因此,这说明在 Envision 解析 Lokad_Orders.tsv 文件时,它会预期列 Quantity 包含可以成功解析为数字的标记。而如果我们编写以下脚本:
Nonsense = sum(Orders.Client)
在此情况下,Envision 将尝试使用数字解析 Lokad_Orders.tsv 文件的 Client 列,这个过程会失败,因为此列包含的是客户标识符,不是数字。 除了类型推断机制,Envision 还提供一种语法,用于显式指定预期的每个表中每列的类型。例如,可以在样本数据集中显式输入以下语句:
expect Supplier : text
expect Orders.NetAmount : number
expect PO.ArrivalDate : date
该语法的作用与 expect MyTable.MyColumn : type 相同,其中 type 是这四种合格类型中的一种:textnumberdateboolean。类型推断使用最为广泛地是 date 类型,因为单纯根据算术运算和类型推断,并非总能正确推断出预期为日期的列。

解析选项

Envision 文件解析程序的耐受性非常高,但是,在某些情况下,解析程序需要获取一些帮助。skip 选项可用于告知解析程序跳过平面文件的前 N 行。语法如下:
read "/foo/bar*.csv" skip:2 as MyTable with "Foo1" as Id, "Foo2" as Date
在上例中,解析程序跳过了平面文件的前两行,预期第三行为列标题。skip 为可选的选项,其默认行为是 skip:0。此选项用于处理在提取的平面文件的开头引入了元数据的系统。

不安全的读取

默认情况下,Envision 的文件解析程序非常严格:如果值的预期输入为日期或数字,并且如果此值无法成功解析,那么 read 声明将因发生错误而失败。根据经验,当 Envision 遇到解析错误时,最好的选择就是第一时间分析文件损坏的原因。实际上,Envision 能够识别许多日期和数字格式,如果出现 Envision 失败的情况,很可能是数据被损坏。数据损坏可能导致各种各样的错误。在 Envision 失败时,多半只是之前发生的某个问题的一种外在表现而已。

但对于较大的数据集,出现轻微的数据损坏在所难免。如果损坏的数据较老,也许就不值得去修复数据损坏。因此,对于这些特殊情况,Envision 支持 unsafe 读取模式,语法如下:
read "/foo/orders.tsv" unsafe with "My Id" as Id, "My Date" as Date
当使用 unsafe 时,Envision 会将解析问题视为警告处理,而不是视为错误处理。这一选项有利于继续向前计算,即便某些值或行因为无法读取而被解析程序丢弃时也是如此。