結合されたセルを含む範囲を操作(コピー/移動)すると、「貼り付けが結合されたセルと重なっています。セルをマージ解除して、再試行してください。」しかし、を使用して範囲内のセルRange#breakApart
をマージ解除しようとすると、「選択したセルをマージできません。」という別のエラーが発生します。これは、何もマージしようとしないため、さらに混乱します。離れた細胞。
4 に答える
呼び出さbreakApart
れた範囲が、マージ領域の一部だけでなく、すべてのマージされたセルを含む場合にのみ機能することがわかります。
これはそれほど悪くはないでしょう。APIにマージされたセルの範囲を取得する方法がないことに気付くと、問題が始まります。したがって、これを解決する最善の方法(これまでに見つけた)は、エラーが発生しなくなるまで範囲を穏やかに拡張することです。
var breakRange = myRange;
for(;;) {
try {
breakRange.breakApart();
break;
} catch(e) {
breakRange = mySheet.getRange(
breakRange.getRowIndex(),
breakRange.getColumnIndex(),
Math.min(
breakRange.getHeight()+5,
mySheet.getMaxRows()-breakRange.getRowIndex()+1
),
Math.min(
breakRange.getWidth()+5,
mySheet.getMaxColumns()-breakRange.getColumnIndex()+1
)
);
}
}
(範囲の取得はかなりコストのかかるプロセスのように思われるため、1つではなく5つの行/列を追加しました)。これは、検索領域を拡張するときに結合されたセルが追加されていない限り、非常にうまく機能します。
スプレッドシート内の結合されたセルに関しては、Google AppsScriptsAPIは基本的に少なくとも次の方法で壊れています。
- シート/範囲内の結合されたセルの範囲の配列を取得する方法はありません。
- どのセルが分割されているかを確認する方法があるはずです(
breakApart
「連鎖のために」元の範囲のみを返します)。これにより、マージを分割してから、各セルに元のマージセルのコンテンツを含めることができなくなります。 breakApart
マージセルの一部のみを含む範囲で使用しようとすると、例外をスローするのではなく、マージ全体を分割する必要があります。
全体として、現在のAPIは、スクリプト作成者自身がレイアウトと使用法を完全に制御できるスプレッドシートに対してのみ機能します。
この関数は、指定されたセルまたは範囲と部分的に交差するマージされたセルの範囲を分解します。このスレッドのAdamMorris( @clssrmtechtools)によって提案されているように、Sheets Advanced Serviceを使用して、特定のシート内のすべてのマージされた範囲を識別します。
デモスプレッドシートはこちら。
/**
* Breaks apart merged cells in range
* @param {sheet} sheet Sheet of range
* @param {range} rangeToSplit Cell or cells that intersect with whole merged range
*/
function breakApartAux(sheet, rangeToSplit) {
// Current spreadsheet & sheet
let ss = SpreadsheetApp.getActiveSpreadsheet();
let activeSSId = ss.getId();
let activeSId = sheet.getSheetId();
// Get sheet's merges using advanced sheets service
let merges = Sheets.Spreadsheets.get(activeSSId).sheets.find(s => s.properties.sheetId == activeSId).merges;
if (merges == undefined) SpreadsheetApp.getUi().alert('No merged cells found in sheet.');
else {
// Logger.log(merges);
// Cells to merge R/C
let rowS = rangeToSplit.getRow();
let rowE = rowS + rangeToSplit.getNumRows() - 1;
let colS = rangeToSplit.getColumn();
let colE = colS + rangeToSplit.getNumColumns() - 1;
// Find overlapping merged range
// Advanced service merged ranges start in 0 and are right-open [..)
let merge = merges.find(m => {
let mRowS = m.startRowIndex + 1;
let mRowE = m.endRowIndex;
let mColS = m.startColumnIndex + 1;
let mColE = m.endColumnIndex;
// Check for overlapping
return ((rowS >= mRowS && rowS <= mRowE) ||
(rowE <= mRowE && rowE >= mRowS) ||
(rowS < mRowS && rowE > mRowE)) &&
((colS >= mColS && colS <= mColE) ||
(colE <= mColE && colE >= mColS) ||
(colS < mColS && colE > mColE));
})
// Overlapping range?
if (merge == undefined) SpreadsheetApp.getUi().alert('No merged cells found in specified range.');
else {
// Break apart whole range
ss.getActiveSheet().getRange(merge.startRowIndex + 1,
merge.startColumnIndex + 1,
merge.endRowIndex - merge.startRowIndex,
merge.endColumnIndex - merge.startColumnIndex).breakApart();
}
}
}
Raphaelの答えに触発されて、これはシート内のすべてのセルをマージ解除する方法です。隣接するヌル値を持つセルをマージするデータインポートに使用したものは次のとおりです。つまり、セルa1とセルb1をマージしていませんでしたが、a1には値があり、b1にはありませんでした。
function unmergeSheet() {
let mySheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
let myRange = mySheet.getDataRange()
myRange.breakApart();
}
JuusoNykänenの提案で更新
これが私が見つけた最も簡単な方法です:
function unmerge() {
var sheetName = 'Sheet1'; // Change!
var a1Notation = 'A1:B15'; // Change!
var range = SpreadsheetApp.getActive().getSheetByName(sheetName).getRange(a1Notation);
var mergedRanges = range.getMergedRanges();
for (var i = 0; i < mergedRanges.length; i++)
{
mergedRanges[i].breakApart();
}
}