2015-07-20 24 views
7

Próbowałem wykonać programowanie przy użyciu języka Java, aby połączyć się z Arkuszem kalkulacyjnym Google, aby pobrać dane lub zmodyfikować dane w komórkach.Java do arkusza kalkulacyjnego Google

Mój związek kalkulacyjny Google jest https://docs.google.com/spreadsheets/d/1UXoGD2gowxZ2TY3gooI9y7rwWTPBOA0dnkeNYwUqQRA

Spojrzałem na Sheets API i wymaga łącza jak

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

Próbowałem różnych form powiązań, takich jak:

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

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

Dali mi różne rodzaje błędów odpowiednio:

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

nie mam pojęcia jak połączyć się z GOOGL kalkulacyjny przy użyciu Java . Pomóż mi, jeśli masz doświadczenie w tej kwestii.

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<SpreadsheetEntry> 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()); 
    } 
} 

nie używałem service.setUserCredentials("[email protected]", "password") bo mam inny błąd, który jest com.google.gdata.util.AuthenticationException: Error authenticating (check service name)

+0

Czy skonfigurowałeś bibliotekę klienta Java? A może używasz surowych żądań REST HTTPS? –

+0

Użyłem maven do importowania biblioteki gdata. Czy powinienem zamiast tego pobrać plik JAR? –

+0

Nie wiem. Chciałem tylko upewnić się, że zrobiłeś podstawy. Pokaż kod Java, który wysyła żądanie. –

Odpowiedz

0

Pasza można uzyskać z tego adresu URL jest WorksheetFeed, a nie SpreadsheetFeed. Spróbuj tego:

SpreadsheetService service = new SpreadsheetService("google-spreadsheet"); 

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

otrzymujesz przekierowanie ponieważ dostępu do arkusza kalkulacyjnego wymaga uwierzytelnienia pierwszy. Arkusze Google używają starego interfejsu API gdata, ale wymagają uwierzytelnienia za pomocą protokołu OAuth 2.0. Dlatego trzeba będzie importować zarówno bibliotek GData i Google API, jak pokazano poniżej:

<dependencies> 
    <dependency> 
     <groupId>com.google.gdata</groupId> 
     <artifactId>core</artifactId> 
     <version>1.47.1</version> 
    </dependency> 
    <dependency> 
     <groupId>com.google.api-client</groupId> 
     <artifactId>google-api-client-java6</artifactId> 
     <version>1.20.0</version> 
    </dependency> 
</dependencies> 

Poniższy kod pokazuje, w jaki sposób można uwierzytelniać z Google przy użyciu protokołu OAuth. Będziesz musiał follow the instructions for creating a service account and downloading the P12 key first. Po utworzeniu konta usługi, skopiuj adres e-mail do pola CLIENT_ID poniżej, dodaj plik P12 do swojej ścieżki klasy i chante P12FILE, aby wskazać plik P12.

Udało mi się uzyskać to działając z następującym SPREADSHEET_FEED_URL "https://spreadsheets.google.com/feeds/worksheets/:worksheetId/private/basic", gdzie ": worksheetId" jest twoim identyfikatorem arkusza roboczego. To trochę różni się od tego, którego używasz.

Upewnij się, że konto usługi ma uprawnienia do odczytu lub zapisu w arkuszu kalkulacyjnym, dzieląc go najpierw z adresem e-mail konta usługi.

public class GoogleSheetsApiTest { 

// Generate a service account and P12 key: 
// https://developers.google.com/identity/protocols/OAuth2ServiceAccount 
private final String CLIENT_ID = "<your service account email address>"; 
// Add requested scopes. 
private final List<String> 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 = "/<your p12 file name>.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<SpreadsheetEntry> 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; 
} 

} 
+0

Cześć Brian, Wielkie dzięki. Poszedłem przez konsolę programisty Google i utworzyłem konto usługi. CLIENT_ID powinien być dłuższy w konsoli programisty lub w moim prawdziwym e-mailu? –

+0

mój kod działa dobrze teraz, dodano 'credential.refreshToken();' po '.setServiceAccountScopes (SCOPES) .build();'. Naprawdę doceniam twoją pomoc, Brian! –

+0

@TimLai Zaakceptuj odpowiedź, jeśli działa. Inni z tym samym problemem będą wiedzieć, na którą odpowiedź szukać. – Teja

0

Czuję, że to błąd. Aby obejść ten problem, możesz najpierw wywołać poniższą prośbę o odesłanie, a następnie zaczną działać prośby o przesłanie.poniżej jest zmodyfikowany kod w celu lepszego zrozumienia:

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<SpreadsheetEntry> 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()); 
    } 
} 

Przeprowadzono również debugowanie. Wydaje się, że jeśli spróbujemy wywołać arkusz z kluczem, odpowiedź wydaje się mieć typ zawartości "application/binary", który będzie rejestrowany w bibliotece gdata, ale jeśli spróbujemy najpierw pobrać wszystkie kanały, odpowiedź będzie miała prawidłowy typ zawartości i tego typu jest używany w następnych żądaniach. więc przepływ zaczyna działać

1

Otrzymałem również błąd com.google.gdata.util.ParseException: Unrecognized content type:application/binary, ale wydaje mi się, że natknąłem się na obejście tego dziwnego błędu. Kod w Alex R's answer może być użyty jako punkt wyjścia.

  1. Najpierw próbowałem zmieniając widoczność "public", żeby zobaczyć co się stanie. Ponieważ dokument nie został opublikowany, otrzymałem oczekiwaną odpowiedź błędu, zawierającą:

    Przykro nam. Ten dokument nie jest opublikowany.

  2. Więc zmienił widoczność do tyłu do "private" i spróbował ponownie tylko dla zabawy ...

    Lo, a oto; zadziałało!

Działa zarówno z napędem lub Arkusze RSS zakres (oba mogą zostać uwzględnione, jeżeli wolisz):

nie jestem pewien, czy to jest czynnik, ale nie używam OAuth 2.0, ale raczej Credential utworzony z PrivateKey (plik PKCS12), jak w Brian Chapman's answer.

Wnioski

Tak, choć to kludgy, I zostały zmodyfikowane mój wniosek do zawsze dokonać "public" żądanie (zawinięte w try bloku wchłonąć wynikowy Exception) tuż przed złożeniem wniosku "private". To jedyny sposób, w jaki udało mi się deterministycznie uzyskać poprawny wynik.

0

1 powodem coraz com.google.gdata.util.RedirectRequiredException: przeniósł się tymczasowo kiedy zapominamy opublikować dokument/arkusz kalkulacyjny. Upewnij się, że opublikowałeś swój dokument po jego utworzeniu, przechodząc do Menu> Plik> Opublikowany do Internetu. Jest to wymagane tylko raz, a nie po każdej edycji.