Javascript 使用应用程序脚本在未定义的工作表中识别相同列中的重复值

Javascript 使用应用程序脚本在未定义的工作表中识别相同列中的重复值,javascript,function,google-apps-script,google-sheets,triggers,Javascript,Function,Google Apps Script,Google Sheets,Triggers,我有一个电子表格,它的数量越来越不明确。 我想突出显示所有未定义图纸中相同列中的重复值。 我可以使用条件格式,但是由于工作表的数量将大量增加,这种方法是无效的 我试过这样的方法: var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getActiveSheet(); var lastRow = sheet.getLastRow(); var lastColumn = sheet.getLastColumn(); func

我有一个电子表格,它的数量越来越不明确。 我想突出显示所有未定义图纸中相同列中的重复值。 我可以使用条件格式,但是由于工作表的数量将大量增加,这种方法是无效的

我试过这样的方法:

var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();

function readSheetData() {
  var rowRange = sheet.getRange(1, 1, lastRow, lastColumn);
  var rangeArray = rowRange.getValues();
  // Convert to a one dimensional array
  rangeArray = [].concat.apply([], rangeArray);
  return rangeArray;
}

// Creates an array with data from a chosen column
function readColumnData(column) {
  var columnRange = sheet.getRange(1, column, lastRow);
  var rangeArray = columnRange.getValues();
  // Convert to one dimensional array
  rangeArray = [].concat.apply([], rangeArray);
  return rangeArray;
}

// Creates an array with data from a chosen row
function readRowData(row) {
  var rowRange = sheet.getRange(row, 1, 1, lastColumn);
  var rangeArray = rowRange.getValues();
  // Convert to one dimensional array
  rangeArray = [].concat.apply([], rangeArray);
  Logger.log(rangeArray);
  return rangeArray;
}

// Sort data and find duplicates
function findDuplicates(data) {
  var sortedData = data.slice().sort();
  var duplicates = [];
  for (var i = 0; i < sortedData.length - 1; i++) {
    if (sortedData[i + 1] == sortedData[i] && sortedData[i] != "") {
      duplicates.push(sortedData[i]);
    }
  }
  return duplicates;
}

// Find locations of all duplicates
function getIndexes(data, duplicates) {
  var column = 2;
  var indexes = [];
  i = -1;
  // Loop through duplicates to find their indexes
  for (var n = 0; n < duplicates.length; n++) {
    while ((i = data.indexOf(duplicates[n], i + 1)) != -1) {
      indexes.push(i);
    }
  }
  return indexes;
}

// Highlight all instances of duplicate values in a sheet
function highlightSheetDuplicates(indexes) {
  var row;
  for (n = 0; n < indexes.length; n++) {
    row = 1;
    if (indexes[n] > lastColumn) {
      row = Math.floor(indexes[n] / lastColumn);
      indexes[n] = indexes[n] - lastColumn * row;
      row++;
    }
    sheet.getRange(row, indexes[n] + 1).setBackground("red");
  }
}


// Highlight all instances of duplicate values in a column
function highlightColumnDuplicates(column, indexes) {
  for (n = 0; n < indexes.length; n++) {
    sheet.getRange(indexes[n] + 1, column).setBackground("red");
  }
}

// Highlight all instances of duplicate values in a row
function highlightRowDuplicates(row, indexes) {
  for (n = 0; n < indexes.length; n++) {
    sheet.getRange(row, indexes[n] + 1).setBackground("red");
  }
}

//----------- Main -------------

function sheetMain() {
  var data = readSheetData();
  var duplicates = findDuplicates(data);
  var indexes = getIndexes(data, duplicates);
  highlightSheetDuplicates(indexes);
}

function columnMain(column) {
  var data = readColumnData(column);
  var duplicates = findDuplicates(data);
  var indexes = getIndexes(data, duplicates);
  highlightColumnDuplicates(column, indexes);
}

function rowMain(row) {
  var data = readRowData(row);
  var duplicates = findDuplicates(data);
  var indexes = getIndexes(data, duplicates);
  highlightRowDuplicates(row, indexes);
}

// ---------- Menu ----------
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('DUPLICATED')
    .addItem('Sheet', 'sheetMain')
    .addItem('Row', 'showRowPrompt')
    .addItem('Column', 'showColumnPrompt')
    .addToUi();
}

// ---------- Prompt ----------
function showColumnPrompt() {
  var ui = SpreadsheetApp.getUi();
  var response = ui.prompt(
    'Find Duplicates',
    'Enter letter of column to search:',
    ui.ButtonSet.OK_CANCEL);
  // Get user response, run main
  var button = response.getSelectedButton();
  var text = response.getResponseText();
  if (button == ui.Button.OK) {
    text = sheet.getRange(text + "1");
    text = text.getColumn();
    columnMain(text);
  }
}

function showRowPrompt() {
  var ui = SpreadsheetApp.getUi();
  var response = ui.prompt(
    'Find Duplicates',
    'Enter number of row to search:',
    ui.ButtonSet.OK_CANCEL);
  // Get user response, run main
  var button = response.getSelectedButton();
  var text = response.getResponseText();
  if (button == ui.Button.OK) {
    rowMain(text);
  }
}
但它仅适用于活动工作表的列/行。 它还启用了一个非常有用的触发器菜单

预期结果:

从菜单中运行脚本 在工作表_1 A:A、工作表_2 A:A、工作表_3 A:A中使用红色背景单元格高亮显示。。。具有相同值的。 对图纸1 D:D、图纸2 D:D、图纸3 D:D中的值执行相同的操作 对活页_1 J:J、活页_2 J:J、活页_3 J:J中的值执行相同的操作 手动删除一些突出显示的行 再次运行脚本 深呼吸,喝点茶 另外,我不想在第一行固定标题中查找重复项

如果有人能帮我解决这个问题,我将不胜感激。我已经工作了三天,没有找到正确的解决方案。我尝试了不同的方法,但我找不到理想的解决方案

谢谢 假设: 原始值来自最早的图纸,所以大多数副本都在以后的图纸中找到,或者至少在第一张图纸的最后一行找到

function findDuplicateInMultipleColumnsAndMultipleSheets() {
  const names = ['Sheet1', 'Sheet2', 'Sheet3'];//sheet names included
  const colors= ['#ff0000','#ffff00','#00ffff'];//added different colors for each column
  const cols = [1, 4, 10];//columns
  const ss = SpreadsheetApp.getActive();
  const shts = ss.getSheets().filter(s => { return ~names.indexOf(s.getName()) });//only gets the sheets with names in the names array
  let uA = new Array(cols.length);//create unique array for all three cols
  cols.forEach((c, i) => {
    uA[i]= new Array(1);
    shts.forEach((sh, j) => {
      let vs = sh.getRange(2, c, sh.getLastRow() - 1, 1).getValues().flat();
      vs.forEach((v, k) => {
        if (!~uA[i].indexOf(v)) {
          uA[i].push(v);//unique array for each column for all three sheets
        }
      });
    })
    let obj={};//used to record first matches which are assumed to be originals
    shts.forEach((sh,j)=>{
       let vs = sh.getRange(2, c, sh.getLastRow() - 1, 1).getValues().flat();
      vs.forEach((e, k) => {
        if (~uA[i].indexOf(e)) {
          if(!obj.hasOwnProperty(e)) {
            obj[e]=1;//first one gets recorded
          } else {
            if(e) {
              sh.getRange(k+2,c).setBackground(colors[i]);//copies get background changed if they're not blank
            }
          }
        }
      });
    })
  });
}
我的数据: 表1:

可乐 可乐 可乐 可乐 可乐 可乐6 可乐 可乐 可乐 可乐 string1 25 25 string1 3. 2. 24 0 1. string1 string2 9 22 string2 23 3. 11 20 4. string2 弦3 7. 28 弦3 19 19 22 7. 3. 弦3 弦4 10 21 弦4 25 12 11 0 0 弦4 弦5 2. 9 弦5 7. 6. 29 15 4. 弦5 第6条 21 26 第6条 21 18 20 1. 6. 第6条 string7 7. 25 string7 3. 21 5. 28 29 string7 第8条 17 2. 第8条 6. 19 20 26 2. 第8条 第9条 9 26 第9条 12 21 20 19 18 第9条 弦4 9 26 弦4 12 21 20 19 18 弦4 9 26 12 21 20 19 18
你做了什么来调试它?是一个重复的行,在每一页的每一列上都是相同的吗?我已经尝试了应用程序脚本调试器,代码运行良好。但是我没有得到我要寻找的结果:在所有工作表中搜索重复项如果你没有得到结果,那么你寻找的一切都不好。是的,每个工作表都有相同的列结构。第一行是header,实际上我不想在这里找到重复的。非常感谢@Cooper,它可以工作!代码中的注释也非常有用。有没有办法避免空白单元格的圆形着色?可能吧。我的数据中没有空白单元格。我来看看它似乎处理的空白情况,多谢“库柏你解决了我的问题!”