Google Drive: Creating a folder

Today I answered a question about how to create a folder in Google Drive . The answer is simple: Google Drive considers a folder to be simply another file, so to create a folder you use the same API call as creating a file, except that you pass in a MIME type of application/vnd.google-apps.folder.

It’s a pretty straightforward answer, but it started me thinking about the nature of folders and Google. It’s interesting that Google Drive supports folders at all, considering that another famous Google service – Gmail – doesn’t support folders at all. Instead, it has labels.

In Gmail, you can create as many labels as you want, and apply any number of them to an email. Labels are similar to folders: they enable users to categorize and easily search for files – the only thing missing is the hierarchical pattern that folders enable. Which leads me back to Google Drive: I wonder how folders are internally represented within the Google Drive system. Based on the API, it looks like folders are considered a special case of files.

But if Drive can handle folders as simply a special file, why doesn’t Gmail support folders as well? Is it simply that Gmail and Drive are separate codebases, or that Google feels that labels are a better categorizing scheme than folders?

It’s always interesting to think about Google’s architecture and how different services have vastly different builds and APIs.

Accessing and searching cells on Google Spreadsheet API

Recently I answered a question on how to access the Google Spreadsheet API. The poster was asking how to search the contents of a row/cell for a specific phrase, so I put together a quick example in Java.

The source code is below. Note that you need to replace the find_word variable with the phrase that you’re searching for, and the username and password variables with your Google username/password.

    try {
        String USERNAME = "username";
        String PASSWORD = "password";
        String find_word = "GOOG";
        find_word = find_word.toLowerCase();
        SpreadsheetService service = new SpreadsheetService(
                "GAEGROUPSEXAMPLENOPROD");
        service.setUserCredentials(USERNAME, PASSWORD);
        URL SPREADSHEET_FEED_URL = new URL(
                "https://spreadsheets.google.com/feeds/spreadsheets/private/full");
        // Make a request to the API and get all spreadsheets.
        SpreadsheetFeed feed = service.getFeed(SPREADSHEET_FEED_URL,
                SpreadsheetFeed.class);
        List<SpreadsheetEntry> spreadsheets = feed.getEntries();
        if (spreadsheets.size() == 0) {
            resp.getWriter().println(
                    "There are no spreadsheets to inspect!");
        }
        // Retrieve an iterator over all spreadsheets contained in
        // this user's Google Drive
        Iterator<SpreadsheetEntry> spreadsheet_iterator = spreadsheets
                .iterator();
        while (spreadsheet_iterator.hasNext()) {
            SpreadsheetEntry spreadsheet = spreadsheet_iterator.next();
            String spreadsheet_name = spreadsheet.getTitle().getPlainText();
            resp.getWriter().println(
                    "Currently searching spreadsheet " + spreadsheet_name);

            // Search only the first worksheet of the spreadsheet.
            WorksheetFeed worksheetFeed = service.getFeed(
                    spreadsheet.getWorksheetFeedUrl(), WorksheetFeed.class);
            List<WorksheetEntry> worksheets = worksheetFeed.getEntries();
            WorksheetEntry worksheet = worksheets.get(0);

            // Fetch the cell feed of the worksheet.
            URL cellFeedUrl = worksheet.getCellFeedUrl();
            CellFeed cellFeed = service
                    .getFeed(cellFeedUrl, CellFeed.class);

            for (CellEntry cell : cellFeed.getEntries()) {
                // Retrieve the contents of each cell.
                String cell_contents = cell.getCell().getInputValue()
                        .toLowerCase();

                // Match the word with the cell contents. Ignoring case.
                if (cell_contents.indexOf(find_word) != -1) {
                    // Found the word.
                    resp.getWriter().println(
                            "Cell with contents " + cell_contents
                                    + " matches your phrase!");
                    // Find the row
                    Integer row_index = new Integer(cell.getCell().getRow());
                    resp.getWriter().println(
                            "<b>Row " + row_index.toString() + "</b> in "
                                    + spreadsheet_name
                                    + " matches your query.");
                    String rowCollect = "";
                    // Print row data
                    URL rowCellFeedUrl = new URI(worksheet.getCellFeedUrl()
                            .toString()
                            + "?min-row="
                            + row_index
                            + "&max-row=" + row_index).toURL();
                    CellFeed rowCellFeed = service.getFeed(rowCellFeedUrl,
                            CellFeed.class);
                    // Iterate through each cell, printing its value.
                    for (CellEntry rowCell : rowCellFeed.getEntries()) {
                        // Print the cell's formula or text value
                        rowCollect += rowCell.getCell().getInputValue()
                                + "\t";
                    }
                    resp.getWriter().println(
                            "<b>Row Data: </b>" + rowCollect);
                }
            }// end for looping through cells
        }// end while looping through spreadsheets

    } catch (Exception e) {
        resp.getWriter().println("Exception: " + e.getMessage());
    }

Also, don’t put this example into production use until you switch out the authentication service to OAuth (this example uses ClientLogin to authenticate).