开放输出:从您的 Web 服务生成 ODF 电子表格

红薯 发布于 2010/02/04 22:47
阅读 438
收藏 0

编写一个生成文本格式的数据的 Web 服务相当简单,但用户通常想得到一些可以在其中工作的文件,比如电子表格。生成电子表格并不是特别复杂,本文介绍一些使用 PHP 和 Python 生成电子表格的方法。

当一个 Web 页面或服务提供数据时,用户特别喜欢使用电子表格的格式获取数据,至少是可以轻松载入电子表格的格式。本文展示如何使用以下两种方法生成 Open Document Format (ODF) 电子表格文件(ODS):一是按字节顺序逐一创建,这需要研究 ODS 文件的内部结构;二是通过可以简化工作的特定库。您还有机会了解到 CSV 文件的创建过程 — 不只因为它们是一种 “最小公分母” 交换格式,还因为您可以将它们自动转换为 ODS 文件。

开始之前

首先要获取一些数据。我使用一个大约包含 300 万条记录的简单数据库(参见 清单 1)— 包含全世界各个国家、地区和城市。我首先从一个包含世界各个城市的自由表(参见 参考资料 获取链接)开始,然后添加 ISO 3166 国家代码表以及 ISO 3166-2 和 FIPS 10-4 地区代码表,因为美国使用早期的代码(而不是后来的更标准的代码)。我添加 completeCities 视图只是为了简化代码示例。您至少需要理解以下几点:

  • 国家 通过一个代码(比如 UY 代表乌拉圭)识别并有一个名称。
  • 国家包含多个地区,地区通过一个代码(在一个国家内是惟一的)识别并有一个名称。
  • 城市 位于一个国家的某个地区并拥有一个名称(有两种名称版本:一个简单的、无重音的 ASCII 名称和一个外国字符名称),一个人口数(如果已知)和地理坐标。


清单 1. 创建一个用于查询的视图

				
CREATE DATABASE world
DEFAULT CHARACTER SET utf8
COLLATE utf8_general_ci;

USE world;

CREATE TABLE countries (
countryCode char(2) NOT NULL,
countryName varchar(50) NOT NULL,
PRIMARY KEY (countryCode),
KEY countryName (countryName)
);

CREATE TABLE regions (
countryCode char(2) NOT NULL,
regionCode char(2) NOT NULL,
regionName varchar(50) NOT NULL,
PRIMARY KEY (countryCode,regionCode),
KEY regionName (regionName)
);

CREATE TABLE cities (
countryCode char(2) NOT NULL,
cityName varchar(50) NOT NULL,
cityAccentedName varchar(50) NOT NULL,
regionCode char(2) NOT NULL,
population bigint(20) NOT NULL,
latitude float(10,7) NOT NULL,
longitude float(10,7) NOT NULL,
KEY `INDEX` (countryCode,regionCode,cityName),
KEY cityName (cityName),
KEY cityAccentedName (cityAccentedName)
);

CREATE VIEW completeCities AS
SELECT
co.countryCode AS countryCode,
co.countryName AS countryName,
re.regionCode AS regionCode,
re.regionName AS regionName,
ci.cityName AS cityName,
ci.population AS population,
ci.latitude AS latitude,
ci.longitude AS longitude
FROM cities ci
JOIN regions re ON re.countryCode=ci.countryCode
AND re.regionCode=ci.regionCode
JOIN countries co ON co.countryCode=re.countryCode
ORDER BY 2,4,5;

 

我还建立了一个简单的页面来测试服务。这个页面允许您输入一个字符串,这些服务通过运行 SELECT * FROM completeCities WHERE cityName LIKE '...%' 获取名称以该字符串开头的城市的数据。这个页面(见 图 1)尽可能 地简单:您只需一个文本框用于输入字符串,并为每个服务提供一个按钮。


图 1. 允许调用不同服务的一个简单页面
这个页面从一个标签为 ‘Start of city name’  的文本字段开始,字段下面是通过以下方法获取城市数据的按钮:PHP generated CSV、PHP generated CSV  variant、Python generated CSV 等。

单击一个按钮将调用对应的服务,生成一个 CSV 文件或一个 ODS 文件(见 图 2)。为稳 妥起见 — 并确保不出现不兼容性 — 我尝试了同时使用 KOffice KSpread 和 OpenOffice.org Calc 来打开所有生成的文件。


图 2. 所有按钮以不同的方式生成相同的结果
图 1 显示的前一个屏幕位于背景中。页面上的一个按钮已经被单击,一个弹出窗口覆盖了屏幕。该窗口的标题是  ‘Opening xml_1_php.ods’。用户可以取消或单击 OK。

首先生成简单的 CSV 文件。通常各类软件都接受 CSV 文件,并可将 CSV 文件作为消息自动传递到 ODS 文件中(尽管需要一些设置步骤)。

使用 PHP 生成 CSV 文件很简单(参见 清单 2 中的代码)。获得想要的数据后,剩下的工作就是检查结果并一次输出一个字段。我将 SELECT 输出限制为 1,000 条记录,但我最多可以获取 65,536 条记录,这是 OpenOffice.org Calc(碰巧也是 Microsoft® Office Excel®)的最大行数,而 KOffice KSpread 只能处理 32,767 条记录。注意,您需要使用 addslashes() 来对字段值进行转义,否则,带有引号的值将中断代码。


清单 2. Csv_1.php 生成一个简单的 CSV 文件

				
// Get the data:

$start= addslashes($_REQUEST["start"]);
$conn= mysql_connect("localhost", "testuser", "testpass");
$db= mysql_select_db("world");
$cur= mysql_query("SELECT * FROM completeCities ".
"WHERE cityName LIKE '{$start}%' LIMIT 1000");

// Send out the data, with headers identifying it as CSV:

header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=csv_1.csv");

while ($row= mysql_fetch_assoc($cur)) {
$sep= "";
foreach ($row as $value) {
$item= is_numeric($value) ? $value : '"'.addslashes($value).'"';
echo $sep.$item;
$sep= ',';
}
echo "\n";
}

 

您可以使用 fputcsv() 更便捷地对主循环编程,fputcsv() 能够帮助处理格式化问题(参见 清单 3)。tmpfile() 能够避免几个用户同时调用这个 Web 脚本时所产生的冲突。文件就绪后,清单 2 中显示的头部将被发送,然后,您需要读取这个临时文件中的内容并输出这些内容。


清单 3. 一个变体 csv_2.php 使用 PHP 的一个 CSV 函数 fputcsv

				
// ...generate results...

$handle= tmpfile();
while ($row= mysql_fetch_assoc($cur)) {
fputcsv($handle, $row);
}

// ...put out headers...

fseek($handle,0);
while ($contents= fread($handle, 1024)) {
print $contents;
}

// ...clean up code...

Python 的 csv 模块能够简化转换工作,如 清单 4 所示。Python 获取数据的方法与 PHP 类似。创建 CSV 文件需要定义要使用的分隔符(逗号 [,])和要引用的 字段;我选择引用所有非数值字段。使用一个 TemporaryFile 将避免编写清理代码;在 Python V2.6 中,SpooledTemporaryFile 的效果更好,因为数据将保存在内存中,除非文件特别大。csv.writer 方法从一个可迭代的对象生成一个 CSV 文件;cursor.fetchall() 功能强大,4 个代码行就足以生成 CSV 输出。下面,与在此前的 PHP 版本中一样,您只需输出头部,临时文件中的数据就会跟着显示出来。





清单 4. Csv_3.py

def index(req):
# ...imports...

# Get the data:

start= req.form["start"]
conn= MySQLdb.connect(host= "localhost", user= "testuser",
passwd= "testpass", db= "world")
cursor= conn.cursor()
cursor.execute("""SELECT * FROM completeCities WHERE
cityName LIKE %s LIMIT 1000""", start+"%")

# Create the CSV file:

csv.register_dialect("simple", delimiter= ',', quoting= csv.QUOTE_NONNUMERIC)
myFile= tempfile.TemporaryFile()
obj= csv.writer(myFile, dialect= "simple")
obj.writerows(cursor.fetchall())

# ...clean up...

# Send back the data, with headers identifying the data as CSV:

req.headers_out.add("Content-type", "text/csv");
req.headers_out.add("Content-Disposition",
"attachment;filename=csv_3.csv");
myFile.seek(0)
return myFile.read()

ODS 文件看起来怎样?

ODS 文件实际上是包含大量文件和目录的 ZIP 文件。并不是所有内容都是必需的,例如,我同时使用 KOffice KSpread 和 OpenOffice.org Calc 创建简单的电子表格(只有单元格 A1 中包含数据 IBM),然后,我解压缩生成的 ODS 文件看看它们包含的内容。清单 5 显示了结果。


清单 5. 检查一个 ODS 文件的内容

				
# unzip -l kspread_ibm.ods
Archive: kspread_ibm.ods
Length Date Time Name
-------- ---- ---- ----
46 08-21-09 14:00 mimetype
2092 08-21-09 14:00 content.xml
2631 08-21-09 14:00 styles.xml
6342 08-21-09 14:00 settings.xml
634 08-21-09 14:00 meta.xml
1171 08-21-09 14:00 Thumbnails/thumbnail.png
786 08-21-09 14:00 META-INF/manifest.xml
-------- -------
13702 7 files

# unzip -l openoffice_ibm.ods
Archive: openoffice_ibm.ods
Length Date Time Name
-------- ---- ---- ----
46 08-21-09 17:00 mimetype
0 08-21-09 17:00 Configurations2/statusbar/
0 08-21-09 17:00 Configurations2/accelerator/current.xml
0 08-21-09 17:00 Configurations2/floater/
0 08-21-09 17:00 Configurations2/popupmenu/
0 08-21-09 17:00 Configurations2/progressbar/
0 08-21-09 17:00 Configurations2/menubar/
0 08-21-09 17:00 Configurations2/toolbar/
0 08-21-09 17:00 Configurations2/images/Bitmaps/
3808 08-21-09 17:00 content.xml
6411 08-21-09 17:00 styles.xml
876 08-21-09 17:00 meta.xml
1012 08-21-09 17:00 Thumbnails/thumbnail.png
7226 08-21-09 17:00 settings.xml
1896 08-21-09 17:00 META-INF/manifest.xml
-------- -------
21275 15 files

 

在这两种情况下,首先包含的文件都是 mimetype,它包含 application/vnd.oasis.opendocument.spreadsheet。 这个文件必须是这个包的 ZIP 文件的第一个流。

另一个常见文件是 thumbnail.png:为了便于呈现,ODF 文件包含一个已保存文档的 128 x 128 缩略图表示。但是,相关规范并不强制包含该图像,因此,针对本示例的目的,您可以跳过这个步骤。

类似地,您可以去掉多数其他文件,但您必须包含带有 manifest.xml 文件和 contents.xml 文件的 META-INF 目录,manifest.xml 文件描述这个 ZIP 文件中包含的所有其他文件,contents.xml 文件存储电子表格的实际内容。经过简单的试验,我确信 KOffice KSpread 和 OpenOffice.org Calc 都能处理这些最少量的内容,因此,我只需创建 3 个文件:

  • 由于 mimetype 文件总是不变的,因此它的生成过程无关紧要。
  • 对于缩减过的内容,manifest.xml 文件的长度只有几行,如 清单 6 所示。
  • 更复杂的文件是 contents.xml。


清单 6. 一个简单的 manifest.xml 文件

				



manifest:media-type='application/vnd.oasis.opendocument.spreadsheet'
manifest:full-path='/' />

manifest:media-type='text/xml'
manifest:full-path='content.xml' />

 

基本上,这个 XML 内容至少应包含一个 office:spreadsheet 元素,该元素本身又包含一个 table:table 元素,用于表示电子表格中的每个单独的工作表。table:table 元素包含多个 table:table-row 元素(一行一个),table:table-cell 元素表示每行中的连续单元,如 清单 7 所示。


清单 7. 只有一个单元格的样例内容文件

				








IBM






注意,这种最小化的内容文件不允许任何样式,但您可以稍后应用样式。下面,让我们开始实际生成一个 ODS 文件。

直接通过 XML 生成 ODS 文件

由于 XML 文件是文本文件且很容易从命令行压缩,因此使用任何脚本语言来生成 ODS 文件都很简单。本文提供两种方法:一种方法是使用 PHP,这种方法比较简单;另一种更详尽的方法是使用 Python,这种方法使用适当的模块。(如果您想进一步改进这个任务,有一些针对 PHP 的 XML 和 ZIP 包可用。)让我们从简单的方法开始(参见 清单 8)。 按照前面的清单中的方法获取数据后,您必须创建 contents.xml 文件,首先包含一个常量头部,然后是结果数据(按照逐行、逐单元的方式),最后是一个结束页脚。manifest.xml 和 mimetype 文件可以通过使用 file_put_contents() 轻松创建。然后,压缩所有文件,将结果 ZIP 文件的所有内容放置到相应头部的后面,最后删除所有额外文件和目录以进行简化。


清单 8. Xml_1.php

				
// ...get the data...

/*
Define the constants that will be needed for the text files
(The constants were somewhat abridged; see the original source code.)
*/

define(MIMETYPE, "application/vnd.oasis.opendocument.spreadsheet");

define(XML_MANIFEST,
"\n".
" ... ");

define(XML_START,
" ... ".
"");

define(XML_ROW_START, "");

define(XML_CELL_START, "");

define(XML_CELL_END, "");

define(XML_ROW_END, "");

define(XML_END,
"");

// Create the content.xml file:

$contents= XML_START;
while ($row= mysql_fetch_assoc($cur)) {
$contents.= XML_ROW_START;
foreach ($row as $value) {
$contents.= XML_CELL_START;
$contents.= htmlentities($value);
$contents.= XML_CELL_END;
}
$contents.= XML_ROW_END;
}
$contents.= XML_END;

// let $tempzip be the name of a temporary file

mkdir($tempzip);
mkdir($tempzip."/META-INF");
file_put_contents($tempzip."/META-INF/manifest.xml", XML_MANIFEST);
file_put_contents($tempzip."/content.xml", $contents);
file_put_contents($tempzip."/mimetype", MIMETYPE);
system("cd {$tempzip}; zip -mr {$tempzip} mimetype META-INF/* content.xml >/dev/null");

// Put out the data:

header("Content-Type: application/vnd.oasis.opendocument.spreadsheet");
header("Content-Disposition: attachment; filename=xml_1.ods");
header("Content-Transfer-Encoding: binary");
readfile($tempzip.".zip");

// ...clean up, using unlink() and rmdir() to delete all created files

 

现在,让我们转到 Python,使用一种更 “模块化” 的方法来在内存中创建 XML 对象,将它们转储到文件,然后使用 zip 模块生成想要的 ODS 文件,如 清单 9 所示。获取数据的方法和 清单 4 的方法相同。manifestXml 对象只需几行代码就可以创建,因为它的内容是固定的。构建 contentXml 对象需要更多代码,因为它是更大、更复杂的结构。注意,您需要对每个光标行进行一次循环(以在 XML 对象中创建一个行),然后再对每个数据字段执行一次循环(以将各单元添加到此前创建的每一行)。获取所有数据后,剩下的工作是编写实际文件,并使用 zip 模块创建所需的 ZIP 文件,最后生成输出头部,头部的后面是已压缩过的内容。


清单 9. Xml_2.py

				
def index(req):
# ...imports...
# ...get the data...
# ...create the manifestXml object...

# Create the contentXml document:

contentXml= getDOMImplementation().createDocument("office",
"office:document-content", None)
contentXml.documentElement.setAttribute("office:version", "1.1")
contentXml.documentElement.setAttribute("xmlns:table",
"urn:oasis:names🇹🇨opendocument:xmlns:table:1.0")

# ...add more attributes to the contentXml object...
# ...add an empty "office:automatic-styles" element to the document...

obd= contentXml.createElement("office:body")
contentXml.documentElement.appendChild(obd)

oss= contentXml.createElement("office:spreadsheet")
obd.appendChild(oss)

table= contentXml.createElement("table:table")
table.setAttribute("table:name", "Results")
oss.appendChild(table)

# Each cursor row becomes a row in the table; each field, a cell:

for datarow in cursor.fetchall():
tablerow= contentXml.createElement("table:table-row")
table.appendChild(tablerow)
for datafield in datarow:
cell= contentXml.createElement("table:table-cell")
tablerow.appendChild(cell)
text= contentXml.createElement("text:p")
cell.appendChild(text)
text.appendChild(contentXml.createTextNode(str(datafield)))

# Create all required directories and files:

tempDir= tempfile.mkdtemp("", "xmlpy")
os.mkdir(tempDir+"/META-INF")

contentFile= open(tempDir+"/content.xml", "w")
contentFile.write(contentXml.toxml())
contentFile.close()

# ...create files "mimetype" and "META-INF/manifest.xml" similarly...

# Zip everything:

myZip= zipfile.ZipFile(tempDir+".zip", "w")
os.chdir(tempDir)
myZip.write("mimetype")
myZip.write("META-INF/manifest.xml")
myZip.write("content.xml")
myZip.close()

# ...read the contents of the created zip file into variable dataToReturn
# ...clean up, by using os.remove() and os.rmdir()
# ...send back dataToReturn, with appropriate headers

 

这个代码很冗长,您完全可以使用 PHP 方法来完成同样的任务,我只是想向您展示处理相同问题的不同方法。下面的小节将介绍一些有助于进一步缩短代码的库。

通过特定的库生成 ODS 文件

手动创建 XML 文件很无趣,但幸运的是,有一些可用于直接生成 ODS 文档的库。我使用的库是 ods-php,甚至只需 ods-php 的 0.1 版(或其他版本)就可以完成这个任务。(您也可以使用这个类来读取 ODF 文件)。而这个库的弊端是除了 PHP 代码本身外不存在任何文档,因此使用这个库必然会进行一些猜测。

获取数据的方法与前面相同。生成一个 ODS 文件需要创建一个 newOds() 对象并使用 addCell 方法向该对象添加单元。单元通过从 0 开始的行和列识别,比如 A1 将是 0 行、0 列。这个对象就绪后,saveOds 方法以适当的 ODS 格式将它存储在磁盘上,剩下的工作是生成适当的头部,后面加上 ODS 文件的内容,如 清单 10 所示。清理工作要求您删除刚才创建的 ODS 文件。


清单 10. Ods_1.php

				
// ...get the data...

// Create an ODS object and load data into it:

$object= newOds();
for ($curRow=0; $row= mysql_fetch_assoc($cur); $curRow++) {
$curCol= 0;
foreach ($row as $value) {
$type= is_numeric($value) ? "float" : "string";
$object->addCell(0, $curRow, $curCol, $value, $type);
$curCol++;
}
}

// Write the object to a temporary file:

$tempname= tempnam("./", "odsphp");
unlink($tempname);
$tempname.= ".ods";
saveOds($object, $tempname);

// ...send out the contents of the $tempname file, with appropriate headers...
// ...clean up...

 

Python 的 Odfpy 模块提供一个类似的、但更充实的库。您可以从头创建各种 ODF 文件,或者将一个现有文档加载到内存,修改它并再次保存。用前面的方法获取数据后,您必须使用 OpenDocumentSpreadsheet() 方法创建一个文档;然后,创建一个表并添加到该文档;最后,通过先将行添加到表,然后向行添加单元来插入数据,如 清单 11 所示。您现在应该熟悉这个代码的最后部分了:生成头部,获取并放置生成的 ODS 文件的内容,然后通过删除额外的文件进行清理。


清单 11. Ods_2.py

				
def index(req):
# ...imports...

# ...get the data...

# Build the ODS object, row by row and cell by cell:

doc= OpenDocumentSpreadsheet()
table= Table(name="Results")

for cursorRow in cursor.fetchall():
tr= TableRow()
table.addElement(tr)
for val in cursorRow:
tc= TableCell()
tc.addElement(P(text=val))
tr.addElement(tc)

doc.spreadsheet.addElement(table)
myFile= tempfile.TemporaryFile()
doc.write(myFile)

# ...clean up...

# ...send back the contents of myFile...
# ...with headers identifying the data as ODS...

 

检查 odfpy 包以获取更多选项。具体而言,您也许会对 xml2odf 脚本感兴趣,该脚本可以帮助生成最终的 ODS 文件。现在,让我们开始考虑如何美化这个 ODS 文件,使其外观更吸引人。

美化 ODS 文件

目前,您已经通过几种不同的方法成功创建了 ODS 文件,但其效果 — 说得婉转些 — 不怎么好看(见 图 3)。因 此,让我们看看两种在您的输出中包含文本样式的方法:一种是简单方法,直接在 PHP 中生成适当的 XML 文件;另一种更复杂的方法是使用 Python 中的 Odfpy 库。


图 3. 目前的结果
一个外观不好看的列示结果的电子表格

使用样式并不会复杂到让人感到恐惧,但的确有许多问题需要考虑。在本例中,我们希望标题样式使用大号字体、粗体和蓝色,列标题为粗体和灰色样 式。我决定使用更容易使用的自动样式;每当您手动对任何单元应用格式时,这些样式将自动创建(所以叫做自动样式)并全部(而不是分别)包含到 content.xml 文件中。您的文档的 office:automatic-styles 元素应该类似于 清单 12


清单 12. 额外生成一些 XML 以美化电子表格

				
.

style:name='bbb'
style:family='table-cell'>.

fo:font-weight='bold'
fo:color='#0000ff'
fo:font-size='15'/>



style:name='bld'
style:family='table-cell'>

fo:font-weight='bold'/>

fo:background-color='#AEAEAE'/>


 

在 PHP 中工作时,上述代码实际上与 清单 10 相同,但您必须修改 XML 文档以包含必要的自动样式元素。注意,我还定义了两个新的单元格前缀,每个都包含一个适当的 table:style-name 属性。最后,只需添加新的主标题,一个用于调整间距的空行以及一个列标题行,如 清单 13 所示。


清单 13. Xml_3.php

				
// ...everything is the same, just up to XML_START:

define(XML_AUTOMATIC_STYLES,
"".
"
"style:family='table-cell'>".
"
"fo:color='#0000ff' fo:font-size='15'/>".
"".
"
"style:family='table-cell'>".
"".
"".
"".
"");

define(XML_START,
"\n".
"
//...many lines...
"office:version='1.1'>".
XML_AUTOMATIC_STYLES.
"".
"".
"");

// ...more define() lines, as earlier, and two new definitions:

define(XML_BBB_CELL_START,
"");

define(XML_BLD_CELL_START,
"");

// ...then, everything the same, up to:

$contents= XML_START;

// Add a big, bold, blue, title, and an empty line:

$contents.= XML_ROW_START;
$contents.= XML_BBB_CELL_START;
$contents.= "Cities whose name starts with '".$start."'";
$contents.= XML_CELL_END;
$contents.= XML_ROW_END;

$contents.= XML_ROW_START;
$contents.= XML_ROW_END;

// Add some titles, in bold:

$contents.= XML_ROW_START;
foreach (array("Country","","Region","","City","Pop","Lat","Long") as $title) {
$contents.= XML_BLD_CELL_START;
$contents.= $title;
$contents.= XML_CELL_END;
}
$contents.= XML_ROW_END;

// ...everything is the same to the end

 

反观 Python,使用 odfpy 创建样式并不困难,但由于文档不能提供足够的帮助,我必须进行几次试验,比较使用 OpenOffice.org Calc 文档的内容获得的结果。您需要创建新的样式并将它们添加到文档的 automaticstyles 部分。这样,添加一个标题和几个列头部就很简单了:只需创建一个单元并指定想要的 stylename(参见 清单 14)。 注意,这段代码的其余部分类似于 清单 11


清单 14. Ods_3.py

				
def index(req)
# ...everything the same as in ods_a.py, up to including these lines:

doc= OpenDocumentSpreadsheet()
table= Table(name="Results")

# Define a "bold big blue" style, and a simple bold on grey one:

bbb= Style(name="bbb", family="table-cell")
bbb.addElement(TextProperties(fontweight="bold", fontsize="13", color="#0000ff"))
doc.automaticstyles.addElement(bbb)

bld= Style(name="bld", family="table-cell")
bld.addElement(TextProperties(fontweight="bold"))
bld.addElement(TableCellProperties(backgroundcolor="#AEAEAE"))
doc.automaticstyles.addElement(bld)

# Add a listing description, in the bold big blue style, and skip a row:

tr= TableRow()
table.addElement(tr)
tc= TableCell(stylename="bbb")
tc.addElement(P(text="Cities whose name starts with '"+start+"'"))
tr.addElement(tc)

table.addElement(TableRow())

# Add some column titles, in the simple bold style:

tr= TableRow()
table.addElement(tr)
for myText in ["Country", "", "Region", "", "City", "Pop", "Lat", "Long"]:
tc= TableCell(stylename="bld")
tc.addElement(P(text=myText))
tr.addElement(tc)

# ...add the data, create the ODS, clean up; everything the same from here onwards

 

经过上述样式设置后,尽管还不太可能获得样式设计奖,但您至少可以获得更美观的外观(参见 图 4)!


图 4. 添加一些标题和样式来美化结果
添加了样式的结果:标题为蓝色,标题行背景为灰色,行标题为粗体

现在,您可以开始考虑在一个电子表格中包含多个页面或工作表,添加公式,甚至包含曲线图,这样,您就可以真正提高您的输出水平了。

结束语

本文介绍了以标准格式生成表格数据和从一个基本 CSV 文件转换到一个完整 ODS 文件的几种方法。要完成后者,可以手动操作(手动生成所有必要的文件、目录和压缩结果),也可以使用适当的库。通过一点额外工作,您也可以生成美观的电子 表格。用户希望能够简化他们的工作,而生成便于使用的电子表格满足了这一需求。现在,您可以开始将这个功能添加到您自己的 Web 页面和服务中。

下载本文代码

加载中
返回顶部
顶部