Kexi 使用指南
本文将引导新用户了解 Kexi 的一系列概念,Kexi 是 KOffice 数据库管理程序。Kexi 中可用的功能范围从简单的表和查询创建到更高级的报告和脚本编写。Kexi 最近作为 KOffice 2.2 的一部分发布。本文旨在为 Kexi 1.6 的新用户和现有用户演示 Kexi 的实用性。
Kexi 2 从 Kexi 1.6 到目前阶段经历了三年的开发,并且由于开发人员数量少,错过了 KOffice 2.0 和 2.1 的发布。像许多开源程序一样,Kexi 完全是在开发人员的业余时间作为爱好开发的。希望现在发布的第一个版本足够稳定以供使用,并且将为未来的版本提供构建基础。
为了成为有用的指南,处理实际用例会很有帮助。作为 Kexi Facebook 页面的所有者(请参阅“资源”),我每周都会通过电子邮件收到各种统计信息的更新。本文的目的是将这些数据从这些电子邮件消息中提取出来,并放入 Kexi 数据库中,以便能够执行查询和报告以显示随时间变化的趋势。
为了获取数据库的数据,我从 KMail 导出了一些电子邮件消息。这创建了一个 .mbox 文件,它基本上是一个包含所有消息的文本文件。可以逐个浏览电子邮件并将详细信息手动输入到表格中,但是由于我已经积累了一些数据,因此我想自动收集数据。这为在 Kexi 中编写脚本来为我完成这项工作提供了一个很好的挑战。
如果您的安装中未包含 Kexi,请查看您的软件包管理器中是否可以作为更新使用。如果不是,您需要使用 KOffice 和 KDE Wiki 上的指南从源代码安装它(请参阅“资源”)。
首先启动 Kexi,然后从启动向导中选择“创建空白数据库”。根据已安装的插件,您将能够创建一个存储为文件的数据库,或者在现有数据库服务器(例如 PostgreSQL 或 MySQL)上创建一个数据库。选择将其存储在文件中对于新用户来说最容易,并且适用于在任何给定时间访问数据库的用户数量有限的情况。Kexi 基于文件的数据库使用 SQLite 作为底层格式,因此它们可以被任何与 SQLite 兼容的程序读取。
数据库需要一个名称(我选择了 kexi_facebook),然后是保存位置。默认位置即可。在此之后,您将看到 Kexi 主窗口。主窗口包含顶部的工具栏和左侧的项目导航器。Kexi 中的主工具栏与其他 KOffice 应用程序不同,它使用选项卡式布局。每个打开的窗口也有一个本地工具栏,其中包含特定于该窗口的选项,例如表、查询、表单、报告和脚本。
从顶部菜单的“创建”选项卡中,选择“表”以启动表设计器。
我通过电子邮件收到的统计信息包括日期、新粉丝数量、墙帖子数量、访问次数和总粉丝数,因此我创建了一个表,其设计模式如图 1 所示。
字段具有名称、类型和注释,并且还可以从右侧的属性编辑器中获得多个属性,例如约束和默认值(如果未给出)。数据库中的每个对象都将具有许多与之关联的属性,属性编辑器允许在单个位置显示和编辑这些属性。
切换到“数据视图”会提示您保存表并显示表数据编辑器,允许手动输入记录,但这没什么乐趣!
有了我新创建的但空的表,我需要自动获取数据。正如我之前提到的,数据在一个包含所有电子邮件消息的 .mbox 文件中。Kexi 支持脚本,脚本可以使用 ECMAScript(又名 JavaScript)、Python 或 Kross(KDE 脚本框架)支持的多种其他语言编写。我选择使用 QTScript 后端,它允许使用 JavaScript 编写,因为我比 Python 更熟悉它。
我的脚本必须打开 .mbox 文件,逐行读取,使用字符串操作抓取所需的数据,并在读取完整的数据集后,将其作为记录添加到数据库中。脚本不仅可以访问内置方法和 Kexi 特定的方法,而且还可以导入包含大量有用函数的库——最有用的库是 Qt 库。我使用 Core 函数来访问文件系统,使用 QTextStream 进行数据读取,并使用 GUI 函数来访问 QMessageBox 以在出现错误时在对话框中显示错误。
这次从“创建”菜单选项卡中,我选择“脚本”。这会在中心窗口中启动脚本编辑器,并在右侧启动属性编辑器。
脚本只有几个属性,类型和解释器。我想要的解释器是 QTScript,类型是“可执行”。可执行脚本是旨在手动运行的脚本。“模块”脚本旨在包含代码的通用模块,可以从其他脚本访问。“对象”脚本是绑定到另一个数据库对象(例如报告)的脚本。
完整脚本如列表 1 所示。
列表 1. Facebook 电子邮件导入脚本
// This script will import data from exported emails // into the facebook_stats table include("qt.core"); include("qt.gui"); var statsFile = new QFile("/home/piggz/kexi_fb/updates.mbox"); var stat_date; var new_fans; var new_posts; var visits; var total_fans; var idx; var conn = Kexi.getConnection(); var table = conn.tableSchema("facebook_stats"); if (statsFile.open(QIODevice.ReadOnly)) { var ts = new QTextStream(statsFile); var i = 0; while (!ts.atEnd()) { // Process the file line by line, // grabbing data and adding records var line = ts.readLine(); // Check date email sent idx = line.indexOf("Date:"); if (idx == 0) { stat_date = Date.parse(line.slice(6, 40)); } // Check for fans idx = line.indexOf("ans this week"); if ( idx >= 0) { new_fans = line.slice(0, idx-2); total_fans = line.slice(line.indexOf("(") + 1, line.indexOf("total") - 1); } // Check for wall posts idx = line.indexOf("all posts"); if (idx >= 0) { new_posts = line.slice(0, idx-2) + 0; } // Check for visits idx = line.indexOf("isits to your"); if (idx >= 0) { visits = line.slice(0,idx-2); // Should have all the data now so insert a record stat_date = new Date(stat_date); var short_date = stat_date.getFullYear() + "-" + pad(stat_date.getMonth() + 1, 2) + "-" + pad(stat_date.getDate(), 2); if (!conn.insertRecord(table, [++i, short_date, new_fans, new_posts, visits, total_fans])) { var msg = "Cannot insert into " + table.caption() + '\n'; msg += "Date: " + stat_date.toDateString() + " " + short_date + '\n'; msg += "New Fans: " + new_fans + '\n'; msg += "Total Fans: " + total_fans + '\n'; msg += "New Posts: " + new_posts + '\n'; msg += "Visits: " + visits; QMessageBox.information(0,"Error", msg); } } } QMessageBox.information(0, "Records Added:", i); } statsFile.close(); function pad(number, length) { var str = '' + number; while (str.length < length) { str = '0' + str; } return str; }
列表 1 中所示的脚本中可能存在的错误是它假定表中没有当前记录,并且它创建的主键从 1 开始。运行一次脚本是可以的,但是如果再次运行,它会尝试覆盖 ID 与它尝试插入的内容匹配的记录。为了使其更健壮,它首先需要找出 ID 字段的当前最大值(这将是练习编写脚本的好方法)。
从脚本工具栏执行时,该脚本收集了 11 条记录的数据,这可以从“表数据视图”中看到(图 3)。
值得指出的是,上面的脚本经过了很多试验和错误,因为它最初并不明显可以导入额外的库或使用 Kexi 特定的函数。文档需要改进,以便新用户更容易使用,并且非常欢迎在 KDE Userbase 网站上提交。
目前,数据的顺序是按照从 KMail 中提取的顺序排列的。因为我需要它按升序日期排列,所以我创建了一个查询来对其进行排序。这次从“创建”选项卡中,我选择了“查询”。我想要除自动递增主键之外的所有字段,因此我将其设置为如图 4 所示。
切换到“数据视图”会执行查询并显示结果(图 5)。
我将查询另存为 qryStats 以用于报告。
Kexi 2 的新功能是报告插件。这允许使用类似于其他数据库系统(如 Microsoft Access、Crystal Reports 或 Oracle Reports)中报告设计器的 GUI 编辑器,直接在 Kexi 中设计和执行报告。在 Kexi 1.6 中,报告可以作为来自 kde-apps.org 的单独附加组件使用,但它没有 Kexi 2 版本中的功能那么多,并且它没有完全集成到应用程序中,因为设计器是一个外部程序。
报告可以打印、另存为 PDF、导出为 HTML 或 OpenDocument 电子表格文件,或者只是保留在数据库中以供实时查看。由于两阶段生成过程,可以将报告保存为所有这些格式。报告首先被呈现为中间描述,然后使用此描述以任何选定的格式生成最终版本。在未来的版本中,很可能会支持额外的格式,例如 OpenDocument Text 和 XML,适用于使用 XSLT 进行进一步处理。
从“创建”选项卡中,我选择“报告”以创建一个带有单个“详细信息”部分的空白报告。报告的结构基于“节”,节可以是页眉或页脚、报告页眉或页脚,或者是数据按字段值分组的“组”节。
最初,我想要的只是数据的简单表格视图,因此除了标题和字段标题之外,所有字段都将进入详细信息部分,字段标题必须进入“页眉”或“报告页眉”。从报告工具栏上的“节编辑器”中,我添加了一个“报告页眉”,并使用菜单栏上的“报告设计”选项卡,我添加了字段和标签以创建报告布局。从侧边栏上的“数据源”选项卡中,我将报告的数据源设置为我上面创建的 qryStats 查询。最后,我将每个字段项的“控件源”属性设置为查询中的相应字段,并将标签的“标题”设置为适当的值。最后,它看起来像图 6,并生成了一个报告,如图 7 所示。
这完成了工作,但它并没有我想象的那么“花哨”。在桌面应用程序中,交替行的背景颜色以使每组数据的开始和结束位置更明显是很常见的,因此让我们尝试一下。
我创建了另一个脚本,但这次将其类型设置为“对象”,因为它将与报告对象关联。报告脚本是事件驱动的——也就是说,每当报告生成中发生某个事件时,都会调用脚本中关联的代码。报告脚本使用 Kross::Object 的功能,其中报告中的每个对象都可以与脚本对象关联,使其本质上更面向对象。每个脚本对象都可以有自己的变量和函数。报告对象可以是报告本身或任何报告节。为了更清楚地说明,最终脚本看起来如图 8 所示。
这是一个非常简单的脚本。有一个名为 detail 的对象,其中包含一个函数 OnRender,每当呈现详细信息节时都会调用该函数。该函数跟踪它被调用的次数并交替背景颜色。脚本的最后一行将 detail 函数与报告的详细信息节关联。
然后,在报告中,我将“解释器类型”设置为 QTScript,并将“对象脚本”属性设置为脚本的名称。重要的是报告和脚本的“解释器类型”都匹配;否则,该脚本将不会在“对象脚本”列表中显示为选项。
现在生成的报告如图 9 所示。
字段上的白色背景不是很好看,所以我回到设计器,将每个字段的“不透明度”属性更改为 0,使其透明,从而生成更合理的报告(图 10)。
我在此阶段的最终要求是拥有更图形化的东西:一个漂亮的图表来显示粉丝随时间变化的趋势。报告设计器允许使用 KDAB 的 KDChart 库创建图表,并在 KOffice 程序 KChart 中使用。它非常强大,允许您将图表数据链接到主报告数据(称为主子链接),但现在,我只需要一个简单的单图表。图表对象期望的数据格式是特定的。必须有两列或更多列数据。第一列用于 X 轴上的标签,所有其他列都用作图表中的系列。我首先创建了一个包含两列的查询,按升序排列的日期和总粉丝数,然后创建了一个新报告。报告本身不是基于任何数据的,因此其“数据源”为空。空数据源将生成一个带有详细信息节的报告,从而提供一个区域来向报告添加最少数量的项目。
在我的详细信息节中,我从报告设计器工具栏添加了一个图表对象,并将其数据源设置为我刚刚生成的查询(图 11)。
您可以看到,即使在设计时,图表对象也能够收集数据并绘制图表的预览。切换到数据视图会显示图表,而没有设计器中的任何额外线条和文本(图 12)。
打印时,表格报告和图表报告看起来都与“数据视图”中一样。当使用 KDE 中的 PDF 打印机选项打印时,图表甚至保留了所有细节,因为它没有转换为位图,而是保存为线条,这使其完全可缩放!
将表格报告另存为 HTML 文档会产生两个选项:另存为表格或使用 CSS。表格选项生成一个 HTML 文件,其中报告中每个字段的文本都另存为表格单元格,每个节都是一行。CSS 选项使用 <div> 标签,并尝试创建一个 HTML 文件,使其与原始文件非常相似,从而允许在任意位置呈现文本和图像。
表格报告也可以很好地导出到 OpenDocument 电子表格文件中,以便在 KSpread 或 OpenOffice.org 中使用(图 13)。
从图中可以看出,一个问题是报告的标题占据了一个单元格,其中包含其他字段标题。这是因为它在同一节中,但是可以通过将标题放入单独的节(例如“页眉”)中轻松修复。
Kexi 2 是一个用于开发数据库应用程序的强大工具。尝试一下,了解更多可能性,如果可以,请在 userbase.kde.org/Kexi 上贡献更多文档,或者加入 Freenode IRC 上的 #kexi 或 #koffice 团队。
资源
Kexi 项目 Facebook 页面:www.facebook.com/kexi.project
构建 KOffice:wiki.koffice.org/index.php?title=Building/Building_KOffice
入门/构建/KDE4:techbase.kde.org/Getting_Started/Build/KDE4
Adam Pigg 是一名软件工程师,他在业余时间为 Kexi 和 KOffice 项目做贡献。他通常可以在 Freenode 上的 #kexi 中找到,他会尽力回答任何问题。