使用SpreadsheetApp实现多书籍章节数据交错排序的问题
问题分析与解决方案
你的代码无法提取章节数较多书籍的超额章节,核心原因有两点:
- 外层循环次数等于书籍数量(而非所有书籍中最多的章节数),导致超过书籍数量的章节无法被遍历到;
- 未检查当前书籍是否存在对应索引的章节,会尝试推送
undefined值,引发错误。
以下是修正后的代码,它会按「同序号章节交错排列」的逻辑,完整保留所有书籍的所有章节:
function jumbling() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const rawSheet = ss.getSheetByName('Raw'); const lastRow = rawSheet.getLastRow(); // 处理无数据的情况 if (lastRow < 2) return; // 获取原始数据(从第2行开始,共8列) const data = rawSheet.getRange(2, 1, lastRow - 1, 8).getValues(); // 按书籍名称分组,收集每本书的所有章节行 const bookGroups = data.reduce((acc, row) => { const bookName = row[3]; acc[bookName] = acc[bookName] || []; acc[bookName].push(row); return acc; }, {}); // 保留书籍在原始数据中首次出现的顺序 const bookNames = [...new Map(data.map(row => [row[3], row[3]])).values()]; // 找到所有书籍中最多的章节数 const maxChapters = Math.max(...bookNames.map(name => bookGroups[name].length)); // 构建交错排列的结果数组 const result = []; for (let chapterIdx = 0; chapterIdx < maxChapters; chapterIdx++) { for (const book of bookNames) { const bookChapters = bookGroups[book]; // 仅当当前书籍存在该序号的章节时,才添加到结果 if (chapterIdx < bookChapters.length) { result.push(bookChapters[chapterIdx]); } } } // 将结果写入Processed工作表 const processedSheet = ss.getSheetByName('Processed'); if (!processedSheet) { SpreadsheetApp.getUi().alert('未找到Processed工作表!'); return; } // 清空原有内容并写入新数据 processedSheet.clearContents(); if (result.length > 0) { processedSheet.getRange(1, 1, result.length, result[0].length).setValues(result); } }
关键改进点
- 按书籍分组:使用
reduce将原始数据按书籍名称分组,便于按章节索引提取内容; - 动态遍历次数:基于所有书籍的最大章节数设置外层循环次数,确保不会遗漏任何章节;
- 存在性检查:在添加章节行前,先确认当前书籍是否有对应序号的章节,避免推送无效值;
- 保留书籍顺序:通过
Map保留书籍在原始数据中首次出现的顺序,保证输出顺序符合预期。
内容的提问来源于stack exchange,提问作者Khan
相关产品推荐
相关产品推荐

