如何将Google电子表格的工作表字符串ID转换为整数索引(GID)?

18

要将谷歌电子表格的单个工作表导出为CSV格式,需要传入整数工作表索引(GID)。

https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=%s&gid=%d&exportFormat=csv

但是,这些信息在哪里找到呢?使用gdata.spreadsheets.client,我可以找到一些工作表的字符串id,例如"oc6, ocv, odf"。

client = gdata.spreadsheets.client.SpreadsheetsClient()
feed = client.GetWorksheets(spreadsheet, auth_token=auth_token)

它返回以下原子 XML。(部分内容)

<entry gd:etag="&quot;URJFCB1NQSt7ImBoXhU.&quot;">
    <id>https://spreadsheets.google.com/feeds/worksheets/0AvhN_YU3r5e9dGpTWGx3UVU3MTczaXJuNEFKQjMwN2c/ocw</id>
    <updated>2012-06-21T08:19:46.587Z</updated>
    <app:edited xmlns:app="http://www.w3.org/2007/app">2012-06-21T08:19:46.587Z</app:edited>
    <category scheme="http://schemas.google.com/spreadsheets/2006" term="http://schemas.google.com/spreadsheets/2006#worksheet"/>
    <title>AchievementType</title>
    <content type="application/atom+xml;type=feed" src="https://spreadsheets.google.com/feeds/list/0AvhN_YU3r5e9dGpTWGx3UVU3MTczaXJuNEFKQjMwN2c/ocw/private/full"/>
    <link rel="http://schemas.google.com/spreadsheets/2006#cellsfeed" type="application/atom+xml" href="https://spreadsheets.google.com/feeds/cells/0AvhN_YU3r5e9dGpTWGx3UVU3MTczaXJuNEFKQjMwN2c/ocw/private/full"/>
    <link rel="http://schemas.google.com/visualization/2008#visualizationApi" type="application/atom+xml" href="https://spreadsheets.google.com/tq?key=0AvhN_YU3r5e9dGpTWGx3UVU3MTczaXJuNEFKQjMwN2c&amp;sheet=ocw"/>
    <link rel="self" type="application/atom+xml" href="https://spreadsheets.google.com/feeds/worksheets/0AvhN_YU3r5e9dGpTWGx3UVU3MTczaXJuNEFKQjMwN2c/private/full/ocw"/>
    <link rel="edit" type="application/atom+xml" href="https://spreadsheets.google.com/feeds/worksheets/0AvhN_YU3r5e9dGpTWGx3UVU3MTczaXJuNEFKQjMwN2c/private/full/ocw"/>
    <gs:rowCount>280</gs:rowCount>
    <gs:colCount>28</gs:colCount>
</entry>

我还尝试了使用sheet参数,但是出现了“无效工作表”错误。

https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=%s&sheet=XXX&exportFormat=csv

我猜应该有一些神奇的函数,但是找不到它们。怎样才能将它们转换为整数ID?或者我可以导出带字符串ID的工作表吗?

编辑:我刚刚使用Python创建了一个转换表格。很脏但是能用 :-(

GID_TABLE = {
    'od6': 0, 
    'od7': 1, 
    'od4': 2, 
    'od5': 3, 
    'oda': 4, 
    'odb': 5, 
    'od8': 6, 
    'od9': 7, 
    'ocy': 8, 
    'ocz': 9, 
    'ocw': 10, 
    'ocx': 11, 
    'od2': 12, 
    'od3': 13, 
    'od0': 14, 
    'od1': 15, 
    'ocq': 16, 
    'ocr': 17, 
    'oco': 18, 
    'ocp': 19, 
    'ocu': 20, 
    'ocv': 21, 
    'ocs': 22, 
    'oct': 23, 
    'oci': 24, 
    'ocj': 25, 
    'ocg': 26, 
    'och': 27, 
    'ocm': 28, 
    'ocn': 29, 
    'ock': 30, 
    'ocl': 31, 
    'oe2': 32, 
    'oe3': 33, 
    'oe0': 34, 
    'oe1': 35, 
    'oe6': 36, 
    'oe7': 37, 
    'oe4': 38, 
    'oe5': 39, 
    'odu': 40, 
    'odv': 41, 
    'ods': 42, 
    'odt': 43, 
    'ody': 44, 
    'odz': 45, 
    'odw': 46, 
    'odx': 47, 
    'odm': 48, 
    'odn': 49, 
    'odk': 50, 
    'odl': 51, 
    'odq': 52, 
    'odr': 53, 
    'odo': 54, 
    'odp': 55, 
    'ode': 56, 
    'odf': 57, 
    'odc': 58, 
    'odd': 59, 
    'odi': 60, 
    'odj': 61, 
    'odg': 62, 
    'odh': 63, 
    'obe': 64, 
    'obf': 65, 
    'obc': 66, 
    'obd': 67, 
    'obi': 68, 
    'obj': 69, 
    'obg': 70, 
    'obh': 71, 
    'ob6': 72, 
    'ob7': 73, 
    'ob4': 74, 
    'ob5': 75, 
    'oba': 76, 
    'obb': 77, 
    'ob8': 78, 
    'ob9': 79, 
    'oay': 80, 
    'oaz': 81, 
    'oaw': 82, 
    'oax': 83, 
    'ob2': 84, 
    'ob3': 85, 
    'ob0': 86, 
    'ob1': 87, 
    'oaq': 88, 
    'oar': 89, 
    'oao': 90, 
    'oap': 91, 
    'oau': 92, 
    'oav': 93, 
    'oas': 94, 
    'oat': 95, 
    'oca': 96, 
    'ocb': 97, 
    'oc8': 98, 
    'oc9': 99
}

1
我正在尝试做更多或更少相同的事情。在我的情况下,我正在以编程方式生成电子表格,并且我需要将单个工作表的链接存储在单独的数据库中。 - Tom
6
好的,Google。这只是一个玩笑,对吧?很有趣。现在我们能否请使用正确的工作表索引而不是这些疯狂的东西? - Roman Starkov
如果有人遇到同样的问题,这里是简单的答案:https://code.google.com/p/gdata-python-client/issues/detail?id=698#c6 - Rozkalns
6个回答

28

我发现你的问题,正在寻找解决方案,而且惊讶的是,这些工作表 ID 实际上与gids一一对应。 我最初以为它们是独立分配的,而不是混淆的练习。

通过反向工程他们用于从表格生成工作表 ID 的公式,我能够找到一个略微更清晰的解决方案:

worksheetID = (gid xor 31578) encoded in base 36

那么,以下是从工作表ID转换到gid的Python代码:

def to_gid(worksheet_id):
    return int(worksheet_id, 36) ^ 31578

这还是有点混乱,但对于GID高于99的情况可以工作,而不需要使用巨大的表格。至少只要他们不改变生成逻辑(他们可能不会这样做,因为这将破坏已经在使用的现有ID),就可以工作。


2
你能指导我们通过找出解决方案的过程吗? - letronje
4
我注意到了重复模式。前四个数以6、7、4、5结尾,接下来的四个数是a(10)、b(11)、8和9——同样的进展方式。我发现这样做可以通过用以10结尾的二进制数对连续的数字执行异或操作得出。这就是我发现这些字符串实际上是数字的原因。它们包含所有字母,所以我想它必须是基于36进制的。从那里找到异或因子就很简单了。 - Jakub Wasilewski
有人有.NET的转换吗? - maguy
5
这是我听过的最疯狂、最随机、最没有文献记录但又根本有序、至关重要的行为。我向Jakub致敬,因为他能够理解这一点,并对整个事情如此冷静。 - David M. Perlman

9
这段代码适用于新版的Google Sheets。
// Conversion of Worksheet Ids to GIDs and vice versa
// od4 > 2
function wid_to_gid(wid) {
    var widval = wid.length > 3 ? wid.substring(1) : wid;
    var xorval = wid.length > 3 ? 474 : 31578;
    return parseInt(String(widval), 36) ^ xorval;
}
// 2 > od4
function gid_to_wid(gid) {
    var xorval = gid > 31578 ? 474 : 31578;
    var letter = gid > 31578 ? 'o' : '';
    return letter + parseInt((gid ^ xorval)).toString(36);
}

5

我不能在Wasilewski的帖子中添加评论,因为显然我缺乏声望,所以这里是基于Wasilewski答案的两个Javascript转换函数:

// Conversion of Worksheet Ids to GIDs and vice versa
// od4 > 2
function wid_to_gid(wid) {
    return parseInt(String(wid),36)^31578
}
// 2> 0d4
function gid_to_wid(gid) {
    // (gid xor 31578) encoded in base 36
    return parseInt((gid^31578)).toString(36);
}

这似乎不再适用于新的Google Sheets。 - Mario

2

这是Buho代码的Java适配版本,可以与新版Google Sheets和传统版Google Spreadsheets一起使用。

// "od4" to 2  (legacy style)
// "ogtw0h0" to 1017661118 (new style)
public static int widToGid(String worksheetId) {

    boolean idIsNewStyle = worksheetId.length() > 3;

    // if the id is in the new style, first strip the first character before converting
    worksheetId = idIsNewStyle ? worksheetId.substring(1) : worksheetId;

    // determine the integer to use for bitwise XOR
    int xorValue = idIsNewStyle ? 474 : 31578;

    // convert to gid
    return Integer.parseInt(worksheetId, 36) ^ xorValue;

}

// Convert 2 to "od4" (legacy style)
// Convert 1017661118 to "ogtw0h0"  (new style)
public static String gidToWid(int gid) {

    boolean idIsNewStyle = gid > 31578;

    // determine the integer to use for bitwise XOR
    int xorValue = idIsNewStyle ? 474 : 31578;

    // convert to worksheet id, prepending 'o' if it is the new style.
    return 
        idIsNewStyle ? 
        'o' + Integer.toString((worksheetIndex ^ xorValue), 36): 
        Integer.toString((worksheetIndex ^ xorValue), 36);

}

太棒了,几年后我注意到你的新表格支持。 - Zig Mandel

0

这是 Buho 和 Julie 代码的 Clojure 改编版本,应该能够与新版 Google Sheets 和传统版 Google Spreadsheets 都兼容。

(defn wid->gid [wid]
  (let [new-wid? (> (.length wid) 3)
        wid      (if new-wid? (.substring wid 1) wid)
        xor-val  (if new-wid? 474 31578)]
    (bit-xor (Integer/parseInt wid 36) xor-val)))

(defn gid->wid [gid]
  (let [new-gid? (> gid 31578)
        xor-val  (if new-gid? 474 31578)
        letter   (if new-gid? "o" "")]
    (str letter (Integer/toString (bit-xor gid xor-val) 36))))

0
如果您正在使用gspread与Python,这是您需要做的:
wid = worksheet.id
widval = wid[1:] if len(wid) > 3 else wid
xorval = 474 if len(wid) > 3 else 31578
gid = int(str(widval), 36) ^ xorval

我可能会为此打开一个PR。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接