将Google Spreadsheets数据与PHP集成,第1部分

2010年12月14日- 添加了带有指向“ 简介结论”第2部分的链接的边栏。 此外,在添加条目2部分相关主题

像大多数人一样,我经常使用电子表格。 它们非常适合平衡支票簿,设置每月预算以及估算和控制项目进度。 但是,大约一年前,我从桌面电子表格应用程序切换到了Google Spreadsheets,这是一项基于云的服务,支持我常用的所有电子表格功能。 此开关为我提供了两个关键优势:

  • 我可以在移动中访问电子表格数据。
  • 与使用桌面应用程序相比,共享和协作编辑要容易得多。

从开发人员的角度来看,使Google Spreadsheets特别有趣的是,它提供了Data API,使开发人员可以轻松地围绕用户空间电子表格数据构建新的应用程序。 您可以通过任何支持XML的开发工具包访问此API,并且Google提供了适用于PHP和Java™技术的客户端库。

在这个由两部分组成的文章中,我向您介绍Google Spreadsheets Data API,并向您展示如何通过PHP应用程序集成和使用云中的电子表格数据。 在第一篇文章中,我介绍了Data API支持的各种提要,并说明了如何使用PHP客户端库从这些提要中读取数据。

了解Google电子表格供稿

在开始使用PHP代码之前,您需要了解Google Spreadsheets Data API的工作方式。 该API接受包含一个或多个输入参数的HTTP请求,并返回包含所请求信息的Atom提要。

Google Spreadsheets Data API提供了许多不同的供稿。 请注意,对于其中一些提要,您需要电子表格ID(ssid)或工作表ID(wsid)来制定提要URL。

  • 电子表格供稿包含用户可用的电子表格列表。 可通过以下网址访问它:https://spreadsheets.google.com/feeds/spreadsheets/private/full
  • 工作表供稿绑定到特定的电子表格,并包含该电子表格中的工作表列表。 可通过以下网址访问它:https://spreadsheets.google.com/feeds/worksheets/<ssid>/private/full
  • 列表和单元格供稿绑定到特定的工作表,并包含组成该工作表的行和单元格。 可通过以下网址访问它们:https://spreadsheets.google.com/feeds/list/<ssid>/<wsid>/private/full

电子表格供稿仅适用于经过身份验证的用户。 取决于相应电子表格的安全性设置,甚至可以在不进行身份验证的情况下访问电子表格供稿,例如工作表,列表和单元格供稿。 例如,可以获取公开显示的电子表格的列表或单元格供稿,而无需身份验证。

清单1演示了典型的电子表格供稿的外观。

清单1.电子表格提要示例
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' 
  xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
  <id>https://spreadsheets.google.com/feeds/spreadsheets/private/full</id>
  <updated>2010-11-05T17:11:33.703Z</updated>
  <category scheme='http://schemas.google.com/spreadsheets/2006'
    term='http://schemas.google.com/spreadsheets/2006#spreadsheet'/>
  <title type='text'>Available Spreadsheets - someuser@gmail.com
  </title>
  <link rel='alternate' type='text/html' href='http://docs.google.com'/>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/spreadsheets/private/full'/>
  <link rel='self' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/spreadsheets/private/full'/>
  <openSearch:totalResults>3</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <entry>
    <id>https://spreadsheets.google.com/feeds/spreadsheets/private/full/ssid</id>
    <updated>2010-11-04T07:24:42.388Z</updated>
    <category scheme='http://schemas.google.com/spreadsheets/2006'
      term='http://schemas.google.com/spreadsheets/2006#spreadsheet'/>
    <title type='text'>Overtime Hours</title>
    <content type='text'>Overtime Hours</content>
    <link rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed' 
      type='application/atom+xml' 
      href='https://spreadsheets.google.com/feeds/worksheets/ssid/private/full'/>
    <link rel='alternate' type='text/html' 
      href='https://spreadsheets.google.com/ccc?key'/>
    <link rel='self' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/spreadsheets/private/full/ssid'/>
    <author>
      <name>someuser</name>
      <email>someuser@gmail.com</email>
    </author>
  </entry>
  <entry>
  ...
  </entry>
</feed>

每个电子表格供稿均以<feed>元素作为根元素打开。 <feed>元素包含一个或多个<entry>元素,每个元素代表一个不同的电子表格。 每个<entry>包含更多详细信息,包括标题,最后更新日期和每个电子表格的作者。

请注意,每个<entry>还包含一个<link rel ='http://schemas.google.com/spreadsheets/2006#worksheetsfeed'...>元素。 该元素指定电子表格工作表供稿的URL,并提供一种向下钻取下一级详细信息的方法。 请求此URL将生成一个工作表供稿,其中包含有关所选电子表格中工作表的信息。 清单2给出了一个这样的工作表提要的示例。

清单2.工作表提要示例
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' 
  xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' 
  xmlns:gs='http://schemas.google.com/spreadsheets/2006'>
  <id>https://spreadsheets.google.com/feeds/worksheets/ssid/private/full</id>
  <updated>2010-11-04T07:23:37.513Z</updated>
  <category scheme='http://schemas.google.com/spreadsheets/2006'
    term='http://schemas.google.com/spreadsheets/2006#worksheet'/>
  <title type='text'>Estimate: Home Renovation</title>
  <link rel='alternate' type='text/html' href='https://spreadsheets.google.com/ccc
    ?key=ssid'/>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/worksheets/ssid/private/full'/>
  <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/worksheets/ssid/private/full'/>
  <link rel='self' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/worksheets/ssid/private/full'/>
  <author>
    <name>vikram.melonfire</name>
    <email>someuser@gmail.com</email>
  </author>
  <openSearch:totalResults>7</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <entry>
    <id>https://spreadsheets.google.com/feeds/worksheets/ssid/private/full/wsid
    </id>
    <updated>2010-11-04T07:22:22.440Z</updated>
    <category scheme='http://schemas.google.com/spreadsheets/2006'
      term='http://schemas.google.com/spreadsheets/2006#worksheet'/>
    <title type='text'>Living Room</title>
    <content type='text'>Living Room</content>
    <link rel='http://schemas.google.com/spreadsheets/2006#listfeed' 
      type='application/atom+xml' href='https://spreadsheets.google.com/feeds/list/ssid/
      wsid/private/full'/>
    <link rel='http://schemas.google.com/spreadsheets/2006#cellsfeed' 
      type='application/atom+xml' href='https://spreadsheets.google.com/feeds/cells/ssid/
      wsid/private/full'/>
    <link rel='http://schemas.google.com/visualization/2008#visualizationApi' 
      type='application/atom+xml' href='https://spreadsheets.google.com/tq?
      key=ssid&sheet=wsid'/>
    <link rel='self' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/worksheets/ssid/private/full/wsid'/>
    <link rel='edit' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/worksheets/ssid/private/full/wsid/key'
    />
    <gs:rowCount>100</gs:rowCount>
    <gs:colCount>20</gs:colCount>
  </entry>
  <entry>
  </entry>
</feed>

在工作表供稿中,每个<entry>包含一组<link>元素。 这些元素指定工作表列表提要,单元格提要,可视化端点和编辑端点的URL。 如果您需要查看或编辑工作表中的信息,它们将很有用。 您可以在本文后面的示例中查看列表示例和单元格供稿。

检索电子表格

Google Spreadsheets feed是用XML编码的,很容易将它们与PHP Web应用程序集成。 一种方法是使用PHP中的SimpleXML扩展来解析API返回的Atom提要,并从中提取相关信息。 但是,当Zend框架包含Zend_Gdata时,为什么要这么做呢?PHP客户端库专门为尝试将PHP应用程序与Google Data API集成的开发人员而设计? 您可以单独下载该库(请参阅参考资料中的链接),它为Google Data API提供了一个方便的,面向对象的界面,其中封装了包括身份验证在内的大多数常见任务,因此您可以自由地专注于核心功能您的应用程序。

安装Zend的GData库后,可以继续使用PHP处理Google Spreadsheets Data API提要的示例。 清单3清单1中提取了提要,并使用Zend_Gdata从中提取相关的数据片段并将其格式化为网页。 请注意,在执行脚本之前,需要使用有效值更新脚本中的用户凭证。

清单3.列出电子表格
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing spreadsheets</title>
    <style>
    body {
      font-family: Verdana;      
    }
    </style>    
  </head>
  <body>
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

    // set credentials for ClientLogin authentication
    $user = "someuser@gmail.com";
    $pass = "somepass";

    try {  
      // connect to API
      $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
      $service = new Zend_Gdata_Spreadsheets($client);

      // get list of available spreadsheets
      $feed = $service->getSpreadsheetFeed();
    } catch (Exception $e) {
      die('ERROR: ' . $e->getMessage());
    }
    ?>
  
    <h2><?php echo $feed->title; ?></h2>
    <div>
    <?php echo $feed->totalResults; ?> spreadsheet(s) found.
    </div>  

    <ul>
    <?php foreach($feed as $entry): ?>
      <li class="name"><?php echo $entry->getTitle(); ?></li>
    <?php endforeach; ?>
    </ul>

  </body>
<html>

清单3首先加载Zend类库,然后初始化Zend_Gdata服务类的实例。 此类使用Zend_Http_Client对象,该对象提供了必要的用户身份验证信息,并打开了与Google Spreadsheets服务的身份验证连接。 打开经过身份验证的连接后, getSpreadsheetFeed()方法将检索电子表格供稿。

getSpreadsheetFeed() API调用的响应是一个类似于清单1的Atom提要,然后将其解析并转换为Zend_Gdata_Spreadsheets_SpreadsheetEntry对象的数组,每个对象代表提要中的一个<entry>。 现在可以遍历数组,通过调用相应条目对象的getTitle()方法来打印每个电子表格的标题。

图1展示了输出的样子,并列出了三个可用电子表格(加班时间,估算值:房屋装修和按地区销售)。

图1.用户电子表格列表
用户电子表格列表的屏幕截图(加班时间,估计:房屋装修和按地区销售)

检索工作表

每个Zend_Gdata_Spreadsheets_SpreadsheetEntry对象还公开一个getWorksheets()方法,该方法访问电子表格的工作表提要,并作为Zend_Gdata_Spreadsheets_WorksheetEntry对象返回工作表列表。 看一下清单4 ,它修改了清单3并列出了电子表格中的工作表。

清单4.列出电子表格和工作表
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing spreadsheets and worksheets</title>
    <style>
    body {
      font-family: Verdana;      
    }
    </style>    
  </head>
  <body>
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

    // set credentials for ClientLogin authentication
    $user = "someuser@gmail.com";
    $pass = "somepass";

    try {  
      // connect to API
      $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
      $service = new Zend_Gdata_Spreadsheets($client);

      // get list of available spreadsheets
      $feed = $service->getSpreadsheetFeed();
    } catch (Exception $e) {
      die('ERROR: ' . $e->getMessage());
    }
    ?>

    <h2><?php echo $feed->title; ?></h2>
    <div>
    <?php echo $feed->totalResults; ?> spreadsheet(s) found.
    </div>  

    <ul>
    <?php foreach($feed as $entry): ?>
      <li class="name"><?php echo $entry->getTitle();  ?></li>
      <ul>
      <?php foreach($entry->getWorksheets() as $ws): ?>
        <li class="name"><?php echo $ws->getTitle(); ?></li>      
      <?php endforeach; ?>
      </ul>
    <?php endforeach; ?>
    </ul>

  </body>
<html>

请注意对每个条目对象的getWorksheets()方法的调用。 此方法为每个电子表格请求工作表供稿,并将结果转换为Zend_Gdata_Spreadsheets_WorksheetEntry对象的集合。 和以前一样,很容易遍历此集合并使用其getTitle()方法显示每个工作表条目的标题。 (查看图2纯文本版本 。)

图2说明了修改后的输出。

图2.用户电子表格和工作表的列表
用户电子表格和工作表列表的屏幕截图

检索工作表行

既然您知道如何获取电子表格和工作表,请考虑如何检索工作表的实际内容。 Google Spreadsheets Data API提供了两种方法来执行此操作:

  • 列表供稿,返回包含工作表行的供稿
  • 单元供稿,返回包含工作表中各个单元的供稿

为了说明这一点,请考虑图3图3显示了“按地区销售”电子表格的示例工作表。 (电子表格显示部门,并按单位和美元列出每个部门的销售额。)

图3.本文使用的示例工作表
本文中使用的示例工作表的屏幕截图

清单5显示了此工作表的相应列表供稿。

清单5.示例列表提要
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' 
  xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'
  xmlns:gsx='http://schemas.google.com/spreadsheets/2006/extended'>
  <id>https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full</id>
  <updated>2010-11-04T07:21:19.158Z</updated>
  <category scheme='http://schemas.google.com/spreadsheets/2006'
    term='http://schemas.google.com/spreadsheets/2006#list'/>
  <title type='text'>North</title>
  <link rel='alternate' type='text/html' 
    href='https://spreadsheets.google.com/ccc?key=ssid'/>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full'/>
  <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full'/>
  <link rel='self' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full'/>
  <author>
    <name>someuser</name>
    <email>someuser@gmail.com</email>
  </author>
  <openSearch:totalResults>3</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <entry>
    <id>https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full/cokwr
    </id>
    <updated>2010-11-04T07:21:19.158Z</updated>
    <category scheme='http://schemas.google.com/spreadsheets/2006'
      term='http://schemas.google.com/spreadsheets/2006#list'/>
    <title type='text'>Sector 1</title>
    <content type='text'>salesunits: 63274, sales: 2214590</content>
    <link rel='self' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full/cokwr'/>
    <link rel='edit' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full/cokwr/
      2ed6e01i15gc7'/>
    <gsx:name>Sector 1</gsx:name>
    <gsx:salesunits>63274</gsx:salesunits>
    <gsx:sales>2214590</gsx:sales>
  </entry>
  <entry>
    <id>https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full/cpzh4
    </id>
    <updated>2010-11-04T07:21:19.158Z</updated>
    <category scheme='http://schemas.google.com/spreadsheets/2006'
      term='http://schemas.google.com/spreadsheets/2006#list'/>
    <title type='text'>Sector 2</title>
    <content type='text'>salesunits: 7263, sales: 254205</content>
    <link rel='self' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full/cpzh4'/>
    <link rel='edit' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/list/ssid/wsid/private/full/
      cpzh4/2ed58j9il57e0'/>
    <gsx:name>Sector 2</gsx:name>
    <gsx:salesunits>7263</gsx:salesunits>
    <gsx:sales>254205</gsx:sales>
  </entry>
  <entry>
  ...
  </entry>
</feed>

清单6显示了此工作表的单元格提要。

清单6.一个示例单元供稿
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' 
  xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' 
  xmlns:gs='http://schemas.google.com/spreadsheets/2006' 
  xmlns:batch='http://schemas.google.com/gdata/batch'>
  <id>https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full</id>
  <updated>2010-11-04T07:20:36.606Z</updated>
  <category scheme='http://schemas.google.com/spreadsheets/2006'
    term='http://schemas.google.com/spreadsheets/2006#cell'/>
  <title type='text'>North</title>
  <link rel='alternate' type='text/html' 
    href='https://spreadsheets.google.com/ccc?key=ssid'/>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full'/>
  <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full'/>
  <link rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full/batch'/>
  <link rel='self' type='application/atom+xml'
    href='https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full'/>
  <author>
    <name>vikram.melonfire</name>
    <email>someuser@gmail.com</email>
  </author>
  <openSearch:totalResults>12</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <gs:rowCount>100</gs:rowCount>
  <gs:colCount>20</gs:colCount>
  <entry>
    <id>https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full/R1C1
    </id>
    <updated>2010-11-04T07:20:36.606Z</updated>
    <category scheme='http://schemas.google.com/spreadsheets/2006'
      term='http://schemas.google.com/spreadsheets/2006#cell'/>
    <title type='text'>A1</title>
    <content type='text'>Name</content>
    <link rel='self' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full/R1C1'/>
    <link rel='edit' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full/R1C1/1fvl7'
    />
    <gs:cell row='1' col='1' inputValue='Name'>Name</gs:cell>
  </entry>
  <entry>
    <id>https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full/R1C2
    </id>
    <updated>2010-11-04T07:20:36.606Z</updated>
    <category scheme='http://schemas.google.com/spreadsheets/2006'
      term='http://schemas.google.com/spreadsheets/2006#cell'/>
    <title type='text'>B1</title>
    <content type='text'>Sales (Units)</content>
    <link rel='self' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full/R1C2'/>
    <link rel='edit' type='application/atom+xml'
      href='https://spreadsheets.google.com/feeds/cells/ssid/wsid/private/full/R1C2
      /rkxyni'/>
    <gs:cell row='1' col='2' inputValue='Sales (Units)'>Sales (Units)</gs:cell>
  </entry>
  <entry>
  ...
  </entry>
</feed>

清单5清单6之间的区别应该很明显。 清单5将工作表的每一行表示为一个条目,而清单6将工作表的每个单元格表示为一个条目。 根据您要如何处理工作表中的数据,需要选择适合您目的的提要。

清单7说明了如何使用Zend_Gdata检索和处理列表供稿。 请注意,对于此列表及其后的列表,您需要使用电子表格或工作表ID或同时使用两者来更新脚本,方法是使用实​​际值替换列表代码中的ssid和wsid变量。

清单7.处理列表提要
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing worksheet contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    div.sheet {
      margin: 10px;
      padding: 10px;
      border: silver 2px dotted;
    }
    div.name {
      color: red; 
      text-decoration: none;
      font-weight: bolder;  
    }    
    table, td {
      border: 1px solid black;
      vertical-align: top;
    }
    </style>    
  </head>
  <body>
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

    // set credentials for ClientLogin authentication
    $user = "someuser@gmail.com";
    $pass = "somepass";

    try {  
      // connect to API
      $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
      $service = new Zend_Gdata_Spreadsheets($client);

      // get spreadsheet entry
      $ssEntry = $service->getSpreadsheetEntry(
        'https://spreadsheets.google.com/feeds/spreadsheets/ssid');
      
      // get worksheets in this spreadsheet
      $wsFeed = $ssEntry->getWorksheets();
    } catch (Exception $e) {
      die('ERROR: ' . $e->getMessage());
    }    
    ?>

    <h2><?php echo $ssEntry->title; ?></h2>

    <?php foreach($wsFeed as $wsEntry): ?>
    <div class="sheet">
      <div class="name">Worksheet: 
        <?php echo $wsEntry->getTitle(); ?></div>
      <table>
      <?php 
      // get list feed for worksheet
      // get individual entries in list
      $listFeed = $service->getListFeed($wsEntry); 
      foreach ($listFeed as $listEntry) {
        echo '<tr>';
        $rowData = $listEntry->getCustom();
        foreach($rowData as $customEntry) {
          echo '<td>' .  $customEntry->getText() . '</td>';
        }
        echo '</tr>';
      }
      ?>
      </table>
    </div>
    <?php endforeach; ?>

  </body>
<html>

清单7使用清单4中解释的getWorksheets()方法来检索指定电子表格的所有工作表,作为Zend_Gdata_Spreadsheets_WorksheetEntry对象的集合。 然后将这些输入对象传递给服务对象的getListFeed()方法,以检索与每个工作getListFeed()对应的列表供稿。

工作表的行表示为Zend_Gdata_Spreadsheets_ListEntry对象,每个对象都具有getCustom()方法。 此方法将每行的单个元素(单元格)返回为数组。 此后,很容易遍历此数组,在表中打印每个单元格的内容。

图4用单个工作表(北,南,东)说明了结果,该工作表列出了各个部门的销售单位和美元。

图4.工作表内容,从列表提要中检索
从列表供稿中检索的工作表内容的屏幕截图

检索工作表单元格

正如您可以使用服务对象的getListFeed()方法获取列表供稿一样,您也可以使用对象getCellFeed()方法获取单元格供稿。 清单8进行了说明。

清单8.处理单元提要
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing worksheet contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    div.sheet {
      margin: 10px;
      padding: 10px;
      border: silver 2px dotted;
    }
    div.name {
      color: red; 
      text-decoration: none;
      font-weight: bolder;  
    }    

    </style>    
  </head>
  <body>
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

    // set credentials for ClientLogin authentication
    $user = "someuser@gmail.com";
    $pass = "somepass";

    try {  
      // connect to API
      $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
      $service = new Zend_Gdata_Spreadsheets($client);

      // get spreadsheet entry
      $ssEntry = $service->getSpreadsheetEntry(
        'https://spreadsheets.google.com/feeds/spreadsheets/ssid');

      // get worksheets in this spreadsheet
      $wsFeed = $ssEntry->getWorksheets();
    } catch (Exception $e) {
      die('ERROR: ' . $e->getMessage());
    }    
    ?>
  
    <h2><?php echo $ssEntry->title; ?></h2>

    <?php foreach($wsFeed as $wsEntry): ?>
    <div class="sheet">
      <div class="name">Worksheet: 
        <?php echo $wsEntry->getTitle(); ?></div>
      <table>
      <?php 
      // get cell feed for worksheet
      // display individual rows and columns from cell feed
      $cellFeed = $service->getCellFeed($wsEntry); 
      echo '<ul>';
      foreach ($cellFeed as $cellEntry) {
        $row = $cellEntry->getCell()->getRow();
        $column = $cellEntry->getCell()->getColumn();
        $value = $cellEntry->getCell()->getText();
        echo "<li>($row, $column) = $value</li>";
      }
      echo '</ul>';
      ?>
      </table>
    </div>
    <?php endforeach; ?>

  </body>
<html>

清单8在单元馈送上运行,因此从清单中提取数据的方法与清单7略有不同。 考虑在清单8中 ,工作表的各个单元格表示为Zend_Gdata_Spreadsheets_CellEntry对象,每个对象都公开了返回Cell对象的getCell()方法。 反过来,此单元格对象公开返回相应单元格的行号,列号和值的方法。 现在,很容易遍历集合并在列表中打印每个单元格的内容。

图5说明了输出结果。

图5.从工作表提要中获取的工作表内容
从单元格提要中检索到的工作表内容的屏幕截图

以数组形式检索工作表数据

Zend_Gdata_Spreadsheets还带有一些快捷方法,这些方法可以将列表和单元格提要转换为本地PHP数组,以便于处理。 例如, getContentsAsRows()方法检索工作表的列表供稿,并将其转换为嵌套PHP数组。 清单9进行了说明。

清单9.处理工作表行的数组
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing worksheet contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    div.sheet {
      margin: 10px;
      padding: 10px;
      border: silver 2px dotted;
    }
    div.name {
      color: red; 
      text-decoration: none;
      font-weight: bolder;  
    }    
    table, td {
      border: 1px solid black;
      vertical-align: top;
    }
    </style>    
  </head>
  <body>
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

    // set credentials for ClientLogin authentication
    $user = "someuser@gmail.com";
    $pass = "somepass";

    try {  
      // connect to API
      $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
      $service = new Zend_Gdata_Spreadsheets($client);

      // get spreadsheet entry
      $ssEntry = $service->getSpreadsheetEntry(
        'https://spreadsheets.google.com/feeds/spreadsheets/ssid');
      
      // get worksheets in this spreadsheet
      $wsFeed = $ssEntry->getWorksheets();
    } catch (Exception $e) {
      die('ERROR: ' . $e->getMessage());
    }
    ?>
  
    <h2><?php echo $ssEntry->title; ?></h2>

    <?php foreach($wsFeed as $wsEntry): ?>
    <div class="sheet">
      <div class="name">Worksheet: 
        <?php echo $wsEntry->getTitle(); ?></div>
      <?php $rows = $wsEntry->getContentsAsRows(); ?>
      <table>
      <?php foreach ($rows as $row): ?>
        <tr>
          <?php foreach($row as $key => $value): ?>
          <td><?php echo $value; ?></td>
          <?php endforeach; ?>
        </tr>
      <?php endforeach; ?>
      </table>
    </div>
    <?php endforeach; ?>

  </body>
<html>

清单9迭代了getWorksheets()方法返回的Zend_Gdata_Spreadsheets_WorksheetEntry对象的集合,并调用每个入口对象的getContentsAsRows()方法以嵌套数组的形式检索每个工作表行的内容。 每行均表示为键值对的关联数组。

图6显示输出。

图6.工作表内容,从列表提要数组中检索
从列表提要数组中检索到的工作表内容的屏幕截图

如果单元格的数据是在您的工作更加普遍,取代调用getContentsAsRows()通过调用getContentsAsCells()清单10 。 此方法返回单元格数据的嵌套数组,每个单元格均由其行和列坐标索引。 嵌套数组中还包括每个单元格的公式和最终值。

清单10.处理工作表单元格数组
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing spreadsheet contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    div.sheet {
      margin: 10px;
      padding: 10px;
      border: silver 2px dotted;
    }
    div.name {
      color: red; 
      text-decoration: none;
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

    // set credentials for ClientLogin authentication
    $user = "someuser@gmail.com";
    $pass = "somepass";

    try {  
      // connect to API
      $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
      $service = new Zend_Gdata_Spreadsheets($client);

      // get spreadsheet entry
      $ssEntry = $service->getSpreadsheetEntry(
        'https://spreadsheets.google.com/feeds/spreadsheets/ssid');

      // get worksheets in this spreadsheet
      $wsFeed = $ssEntry->getWorksheets();
    } catch (Exception $e) {
      die('ERROR: ' . $e->getMessage());
    }
    ?>
  
    <h2><?php echo $ssEntry->title; ?></h2>

    <?php foreach($wsFeed as $wsEntry): ?>
    <div class="sheet">
      <div class="name">Worksheet: 
        <?php echo $wsEntry->getTitle(); ?></div>
      <?php $cells = $wsEntry->getContentsAsCells(); ?>
      <ul>
      <?php foreach ($cells as $location => $data): ?>
        <li>
          <?php echo $location; ?> = <?php echo $data['value']; ?>
          <?php echo ($data['formula'] != $data['value']) ? ' *' : ''; ?>
        </li>
      <?php endforeach; ?>
    </div>
    <?php endforeach; ?>

  </body>
<html>

图7显示了清单10返回的数据。 如果通过公式生成单元格值,则该值用星号突出显示。 (查看图7纯文本版本 。)

图7.从工作表提要数组中检索的工作表内容
从单元提要数组中检索到的工作表内容的屏幕截图

筛选工作表数据

您还可以过滤列表供稿或单元格供稿的内容,以使供稿仅返回符合特定条件的行或单元格。 为了说明这一点,请考虑清单11 ,它过滤列表提要以仅返回那些显示超过25,000个销售单位的条目。

清单11.过滤工作表列表提要
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Filtering worksheet contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    div.sheet {
      margin: 10px;
      padding: 10px;
      border: silver 2px dotted;
    }
    div.name {
      color: red; 
      text-decoration: none;
      font-weight: bolder;  
    }    
    table, td {
      border: 1px solid black;
      vertical-align: top;
    }
    </style>    
  </head>
  <body>
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

    // set credentials for ClientLogin authentication
    $user = "someuser@gmail.com";
    $pass = "somepass";

    try {  
      // connect to API
      $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
      $service = new Zend_Gdata_Spreadsheets($client);

      // define worksheet query
      // get list feed for query
      $query = new Zend_Gdata_Spreadsheets_ListQuery();
      $query->setSpreadsheetKey('ssid');
      $query->setWorksheetId('wsid');
      $query->setSpreadsheetQuery('salesunits > 25000');
      $listFeed = $service->getListFeed($query);  
    } catch (Exception $e) {
      die('ERROR: ' . $e->getMessage());
    } 
    ?>
  
    <div class="sheet">
      <div class="name">Worksheet: 
        <?php echo $listFeed->getTitle(); ?></div>
      <table>
      <?php 
      foreach ($listFeed as $listEntry) {
        echo '<tr>';
        $rowData = $listEntry->getCustom();
        foreach($rowData as $customEntry) {
          echo '<td>' .  $customEntry->getText() . '</td>';
        }
        echo '</tr>';
      }
      ?>
      </table>
    </div>

  </body>
<html>

清单11初始化了Zend_Gdata_Spreadsheets_ListQuery对象,该对象可以作为附加参数传递给服务对象的getListFeed()方法,以过滤列表提要中返回的数据。 必须使用三个输入初始化该对象:

  • 电子表格ID
  • 工作表ID
  • 筛选条件

结果是一个列表供稿,其中仅包含那些与过滤条件匹配的工作表行。

过滤条件指定为列名,然后是等号,不等式或布尔运算符,然后是过滤器值。 将查询传输到Data API服务器时,Zend_Gdata自动对过滤器条件进行URL编码。

图8说明了结果。

图8.工作表内容,按销售单位过滤
工作表内容的屏幕截图,按销售单位过滤

同样,可以通过初始化Zend_Gdata_Spreadsheets_CellQuery对象并将此对象传递给getCellFeed()方法来限制单元格提要中返回的数据。 考虑清单12 ,该清单仅通过检索指定工作表的标题行进行演示:

清单12.过滤工作表的单元格提要
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Filtering worksheet contents</title>
    <style>
    body {
      font-family: Verdana;
    }
    div.sheet {
      margin: 10px;
      padding: 10px;
      border: silver 2px dotted;
    }
    div.name {
      color: red; 
      text-decoration: none;
      font-weight: bolder;  
    }
    table, td {
      border: 1px solid black;
      vertical-align: top;
    }
    </style>
  </head>
  <body>
    <?php
    // load Zend Gdata libraries
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

    // set credentials for ClientLogin authentication
    $user = "someuser@gmail.com";
    $pass = "somepass";

    try {  
      // connect to API
      $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
      $service = new Zend_Gdata_Spreadsheets($client);

      // define worksheet query
      // get list feed for query
      $query = new Zend_Gdata_Spreadsheets_CellQuery();
      $query->setSpreadsheetKey('ssid');
      $query->setWorksheetId('wsid');
      $query->setMinRow(1);
      $query->setMaxRow(1);
      $cellFeed = $service->getCellFeed($query);
    } catch (Exception $e) {
      die('ERROR: ' . $e->getMessage());
    }
    ?>

    <div class="sheet">
      <div class="name">Worksheet: <?php echo $cellFeed->getTitle(); ?>
      </div>
      <table>
      <?php 
      echo '<tr>';
      foreach ($cellFeed as $cellEntry) {
        echo '<td>' .  $cellEntry->getCell()->getText() . '</td>';
      }
      echo '</tr>';
      ?>
      </table>
    </div>

  </body>
<html>

清单12初始化了Zend_Gdata_Spreadsheets_CellQuery,然后使用查询对象的setMinRow()setMaxRow()setMinColumn()setMaxColumn()方法定义了应该在提要中返回的单元格范围。 所得的供稿仅包含指定范围内的单元格。 图9说明了结果。

图9.工作表内容,按行号过滤
工作表内容的屏幕截图,按行号过滤

示例应用程序:基于浏览器的电子表格查看器

现在,您已经知道了从Google Spreadsheets Data API检索数据的基础知识,现在来看一个实际的示例,将其置于上下文中。 下一个应用程序使用PHP和JavaScript的组合来呈现一个反映在线工作表内容的数据网格。 它利用jQuery和jqGrid( 有关下载链接,请参阅参考资料)生成数据网格,并使用PHP连接到Google Spreadsheets,检索工作表内容并将它们格式化为适合jqGrid使用的XML文档。

清单13具有连接到Google Spreadsheets Data APIPHP代码,执行查询以获取工作表的列表供稿,并将结果数据转换为jqGrid的XML格式。

清单13.检索和重新格式化工作表的列表提要
<?php
// get page number from request
$page = $_GET['page']; 
if (empty($page)) {
  $page = 1;
}

// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// set credentials for ClientLogin authentication
$user = "someuser@gmail.com";
$pass = "somepass";

// set records per page
$recordsPerPage = 5;
$startIndex = (($page-1) * $recordsPerPage)+1;

try {
  // connect to API
  $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
  $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  $service = new Zend_Gdata_Spreadsheets($client);

  // get spreadsheet entry
  $query = new Zend_Gdata_Spreadsheets_ListQuery();
  $query->setSpreadsheetKey('ssid');
  $query->setWorksheetId('wsid');
  $query->setStartIndex($startIndex);
  $query->setMaxResults($recordsPerPage);
  $listFeed = $service->getListFeed($query); 
  $totalRecords = (string)$listFeed->getTotalResults()+0; // cast to integer

  // send XML headers
  header("Content-type: text/xml"); 
  echo "<?xml version='1.0'?" . ">\n";

  // send summary information
  echo '<rows>'; 
  echo '<page>' . $page . '</page>';
  echo '<total>' . ceil($totalRecords/$recordsPerPage) . '</total>';
  echo '<records>' . $totalRecords . '</records>';

  // send records
  foreach ($listFeed as $listEntry) {
    echo '<row>';
    $rowData = $listEntry->getCustom();
    foreach($rowData as $customEntry) {
      echo '<cell>' .  $customEntry->getText() . '</cell>';
    }
    echo '</row>';
  }
  echo '</rows>';
} catch (Exception $e) {
  die('ERROR: ' . $e->getMessage());
}    
?>

注意, 清单13实现了一个简单的分页系统,该系统期望请求URL中有一个页码。 然后使用该页码来计算要为当前页返回的记录片段,并且setStartIndex()setMaxResults()方法负责相应地配置列表提要。

图10说明了清单13返回的XML格式。 (查看图10纯文本版本 。)

图10.清单13的XML输出
清单13的XML输出的屏幕截图

jqGrid使用清单14中的代码读取此XML格式并将其转换为数据网格。

清单14.将电子表格显示为客户端数据网格
<html>
  <head>
    <link rel="stylesheet" type="text/css" media="screen"
      href="jquery-ui-1.8.6.custom.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="ui.jqgrid.css" />
    <script src="jquery-1.4.2.min.js" type="text/javascript"></script>
    <script src="jquery.jqGrid.min.js" type="text/javascript"></script>  
    <script src="grid.locale-en.js" type="text/javascript"></script>
  </head>
  <body>
    <table id="list1">
    </table> 
    <div id="pager1">
    </div> 
    <script type="text/javascript">
    // code based on XML example at: http://www.trirand.com/blog/jqgrid/jqgrid.html
    jQuery().ready(function (){
      jQuery("#list1").jqGrid({
        url:'generate.php',
        datatype: "xml",
        colNames:
          ['Sector','Sales (Units)', 'Sales ($)'],
        colModel:
          [
            {name:'sector'},
            {name:'salesunits'},
            {name:'sales'},
          ],
        pager: jQuery('#pager1'),
        rowNum:5,
        autowidth: true,
        viewrecords: true,
      }).navGrid('#pager1',{edit:false,add:false,del:false})
      });
    </script>
  </body>
</html>

图11说明了结果输出(销售区域的每个部门在电子表格中按单位和美元显示其销售额)。

图11.从Google Spreadsheets feed生成的客户端数据网格
从Google Spreadsheets feed生成的客户端数据网格的屏幕截图

结论

如这些示例所示,通过Google Spreadsheets Data API,可以轻松地将Google Spreadsheet中的数据直接集成到PHP应用程序中。 本文重点介绍了如何从Google Spreadsheets中检索数据,向您介绍了可用的基本供稿类型,并说明了如何将它们与Zend_Gdata结合使用。 它解释了如何检索用户的电子表格,检查每个电子表格以检索可用工作表的列表,然后使用列表和单元供稿来访问电子表格的实际内容。 它还向您介绍了数据过滤的基础知识,解释了如何显示与特定条件或范围约束匹配的电子表格行或单元格。

但这还不是全部。 使用Google Spreadsheets Data API,您可以通过添加,编辑和删除单元格,行和工作表来查看和更改PHP应用程序中的电子表格数据。 本文的第二部分详细研究了Google Spreadsheets Data API的这些方面,因此请务必回顾一下该文章。


翻译自: https://www.ibm.com/developerworks/xml/library/x-googledata1/index.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值