Java到Google电子表格

我试图使用Java进行编程以连接到Google Spreadsheet来进行数据检索或修改单元格中的数据。

我的Google电子表格链接是https://docs.google.com/spreadsheets/d/1UXoGD2gowxZ2TY3gooI9y7rwWTPBOA0dnkeNYwUqQRA

我查看了Sheets API ,它需要链接

https://spreadsheets.google.com/feeds/worksheets/key/private/full

我尝试过不同forms的链接,例如:

  1. https://spreadsheets.google.com/feeds/worksheets/1UXoGD2gowxZ2TY3gooI9y7rwWTPBOA0dnkeNYwUqQRA/private/full

  2. https://spreadsheets.google.com/feeds/worksheets/1UXoGD2gowxZ2TY3gooI9y7rwWTPBOA0dnkeNYwUqQRA/private/full

他们分别给了我不同的错误:

  1. com.google.gdata.util.ParseException: Unrecognized content type:application/binary
  2. com.google.gdata.util.RedirectRequiredException: Moved Temporarily

我不知道如何使用Java连接到Googl电子表格。 如果您有这方面的经验,请帮助我。

 import com.google.gdata.client.authn.oauth.*; import com.google.gdata.client.spreadsheet.*; import com.google.gdata.data.*; import com.google.gdata.data.batch.*; import com.google.gdata.data.spreadsheet.*; import com.google.gdata.util.*; import org.testng.annotations.Test; import java.io.IOException; import java.net.*; import java.util.*; public class TestGoogleSheetsAPI { @Test public void testConnectToSpreadSheet() throws ServiceException, IOException { SpreadsheetService service = new SpreadsheetService("google-spreadsheet"); URL SPREADSHEET_FEED_URL = new URL("https://spreadsheets.google.com/feeds/worksheets/1UXoGD2gowxZ2TY3gooI9y7rwWTPBOA0dnkeNYwUqQRA/public/full"); SpreadsheetFeed feed = service.getFeed(SPREADSHEET_FEED_URL, SpreadsheetFeed.class); List spreadsheets = feed.getEntries(); if (spreadsheets.size() == 0) { // TODO: There were no spreadsheets, act accordingly. } SpreadsheetEntry spreadsheet = spreadsheets.get(0); System.out.println(spreadsheet.getTitle().getPlainText()); } } 

我没有使用service.setUserCredentials("xxx@gmail", "password")因为我还有另一个错误,即com.google.gdata.util.AuthenticationException: Error authenticating (check service name)

您正在获取重定向,因为访问您的电子表格需要您首先进行身份validation。 Google表格使用旧的gdata API,但要求您使用OAuth 2.0进行身份validation。 因此,您需要导入gdata和Google API库,如下所示:

   com.google.gdata core 1.47.1   com.google.api-client google-api-client-java6 1.20.0   

以下代码显示了如何使用OAuth对Google进行身份validation。 您需要按照创建服务帐户的说明并首先下载P12密钥。 创建服务帐户后,将电子邮件地址复制到下面的CLIENT_ID字段中,将P12文件添加到类路径中,然后选择P12FILE指向您的P12文件。

我能够使用以下SPREADSHEET_FEED_URL“ https://spreadsheets.google.com/feeds/worksheets/:worksheetId/private/basic ”,其中“:worksheetId”是您的工作表ID。 这与您使用的略有不同。

请务必先通过与服务帐户电子邮件地址共享,确保您的服务帐户具有读取或写入电子表格的权限。

 public class GoogleSheetsApiTest { // Generate a service account and P12 key: // https://developers.google.com/identity/protocols/OAuth2ServiceAccount private final String CLIENT_ID = ""; // Add requested scopes. private final List SCOPES = Arrays .asList("https://spreadsheets.google.com/feeds"); // The name of the p12 file you created when obtaining the service account private final String P12FILE = "/.p12"; @Test public void testConnectToSpreadSheet() throws GeneralSecurityException, IOException, ServiceException, URISyntaxException { SpreadsheetService service = new SpreadsheetService( "google-spreadsheet"); GoogleCredential credential = getCredentials(); service.setOAuth2Credentials(credential); URL SPREADSHEET_FEED_URL = new URL( "https://spreadsheets.google.com/feeds/worksheets/1UXoGD2gowxZ2TY3gooI9y7rwWTPBOA0dnkeNYwUqQRA/private/basic"); SpreadsheetFeed feed = service.getFeed(SPREADSHEET_FEED_URL, SpreadsheetFeed.class); List spreadsheets = feed.getEntries(); if (spreadsheets.size() == 0) { // // TODO: There were no spreadsheets, act accordingly. } // SpreadsheetEntry spreadsheet = spreadsheets.get(0); System.out.println(spreadsheet.getTitle().getPlainText()); } private GoogleCredential getCredentials() throws GeneralSecurityException, IOException, URISyntaxException { JacksonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); HttpTransport httpTransport = GoogleNetHttpTransport .newTrustedTransport(); URL fileUrl = this.getClass().getResource(P12FILE); GoogleCredential credential = new GoogleCredential.Builder() .setTransport(httpTransport) .setJsonFactory(JSON_FACTORY) .setServiceAccountId(CLIENT_ID) .setServiceAccountPrivateKeyFromP12File( new File(fileUrl.toURI())) .setServiceAccountScopes(SCOPES).build(); return credential; } } 

我还得到了com.google.gdata.util.ParseException: Unrecognized content type:application/binary错误,但我似乎偶然发现了这个奇怪错误的解决方法。 Alex R的答案中的代码可以作为起点。

  1. 首先,我尝试将可见性更改为"public" ,只是为了看看会发生什么。 由于文档未发布,我得到了预期的错误响应,包含:

    我们很抱歉。 本文档未发布。

  2. 所以我将知名度改回"private" ,并再次尝试只是为了好玩……

    瞧,看哪; 有效!

它适用于Drive或Spreadsheets Feed范围(如果您愿意,可以包括两者):

我不确定它是否是一个因素,但我不是使用OAuth 2.0,而是使用PrivateKey (PKCS12文件)创建的Credential ,如Brian Chapman的回答 。

结论

所以,尽管它很糟糕,但我已经修改了我的应用程序,以便在发出"private"请求之前始终发出"public"请求(包含在try块中以吸收生成的Exception )。 这是我能够确定性地获得正确结果的唯一方法。

您从该URL获取的Feed是WorksheetFeed ,而不是SpreadsheetFeed 。 尝试这个:

  SpreadsheetService service = new SpreadsheetService("google-spreadsheet"); FeedURLFactory urlFactory = FeedURLFactory.getDefault(); WorksheetFeed worksheetFeed = service.getFeed(urlFactory.getWorksheetFeedUrl("1V4jT4vSqmY4YNY1VJhariLRLbxfFWf5z8bSTpDcSBPE", "public", "full"), WorksheetFeed.class); List worksheets = worksheetFeed.getEntries(); WorksheetEntry worksheet = worksheets.get(0); System.out.println(worksheet.getTitle().getPlainText()); 

我觉得这是一个错误。 作为一种变通方法,您可以先调用以下getfeed请求,然后您的Feed请求将开始工作。 下面是修改后的代码,以便更好地理

 import com.google.gdata.client.authn.oauth.*; import com.google.gdata.client.spreadsheet.*; import com.google.gdata.data.*; import com.google.gdata.data.batch.*; import com.google.gdata.data.spreadsheet.*; import com.google.gdata.util.*; import org.testng.annotations.Test; import java.io.IOException; import java.net.*; import java.util.*; public class TestGoogleSheetsAPI { @Test public void testConnectToSpreadSheet() throws ServiceException, IOException { SpreadsheetService service = new SpreadsheetService("google-spreadsheet"); URL SPREADSHEET_FEED_URL = new URL("https://spreadsheets.google.com/feeds/worksheets/1UXoGD2gowxZ2TY3gooI9y7rwWTPBOA0dnkeNYwUqQRA/public/full"); //added new line ******************************* service.getFeed(new URL("https://spreadsheets.google.com/feeds/spreadsheets/private/full?xoauth_requestor_id=test"),WorksheetFeed.class); //************************ SpreadsheetFeed feed = service.getFeed(SPREADSHEET_FEED_URL, SpreadsheetFeed.class); List spreadsheets = feed.getEntries(); if (spreadsheets.size() == 0) { // TODO: There were no spreadsheets, act accordingly. } SpreadsheetEntry spreadsheet = spreadsheets.get(0); System.out.println(spreadsheet.getTitle().getPlainText()); } } 

做了一些调试。 似乎我们尝试用密钥调用工作表,然后响应似乎有内容类型“application / binary”将在gdata库中重新定位,但如果我们尝试首先获取所有的feed,那么响应将具有正确的内容类型和该类型用于下一个请求。 所以流程开始工作

获取com.google.gdata.util.RedirectRequiredException的一个原因:暂时移动是我们忘记发布文档/电子表格的原因。 通过转到菜单>文件>发布到Web,确保在创建文档后发布了文档。 这只需要一次,而不是每次编辑后都需要。