Или лучше в VBA погрузиться для решения подобных задач?
Function FilenamesCollection(ByVal FolderPath As String, Optional ByVal Mask As String = "", _
Optional ByVal SearchDeep As Long = 999) As Collection
' © EducatedFool excelvba.ru/code/FilenamesCollection
' Получает в качестве параметра путь к папке FolderPath,
' маску имени искомых файлов Mask (будут отобраны только файлы с такой маской/расширением)
' и глубину поиска SearchDeep в подпапках (если SearchDeep=1, то подпапки не просматриваются).
' Возвращает коллекцию, содержащую полные пути найденных файлов
' (применяется рекурсивный вызов процедуры GetAllFileNamesUsingFSO)
Set FilenamesCollection = New Collection ' создаём пустую коллекцию
Set FSO = CreateObject("Scripting.FileSystemObject") ' создаём экземпляр FileSystemObject
GetAllFileNamesUsingFSO FolderPath, Mask, FSO, FilenamesCollection, SearchDeep ' поиск
Set FSO = Nothing ' очистка строки состояния Excel
End Function
Function GetAllFileNamesUsingFSO(ByVal FolderPath As String, ByVal Mask As String, ByRef FSO, _
ByRef FileNamesColl As Collection, ByVal SearchDeep As Long)
' перебирает все файлы и подпапки в папке FolderPath, используя объект FSO
' перебор папок осуществляется в том случае, если SearchDeep > 1
' добавляет пути найденных файлов в коллекцию FileNamesColl
On Error Resume Next: Set curfold = FSO.GetFolder(FolderPath)
If Not curfold Is Nothing Then ' если удалось получить доступ к папке
' раскомментируйте эту строку для вывода пути к просматриваемой
' в текущий момент папке в строку состояния Excel
' Application.StatusBar = "Поиск в папке: " & FolderPath
For Each fil In curfold.Files ' перебираем все файлы в папке FolderPath
If fil.Name Like "*" & Mask Then FileNamesColl.Add fil.Path
Next
SearchDeep = SearchDeep - 1 ' уменьшаем глубину поиска в подпапках
If SearchDeep Then ' если надо искать глубже
For Each sfol In curfold.SubFolders ' перебираем все подпапки в папке FolderPath
GetAllFileNamesUsingFSO sfol.Path, Mask, FSO, FileNamesColl, SearchDeep
Next
End If
Set fil = Nothing: Set curfold = Nothing ' очищаем переменные
End If
End Function
Sub LoopThroughFiles(ByVal sDirName As String, ByRef lRow As Long, ByVal sMask As String)
On Error Resume Next
Dim folder$, coll As Collection
Dim EX As Excel.Application
Dim wkb As Workbook
Dim wks As Worksheet
Dim file As Variant
Dim i As Long
Dim v As Variant
folder$ = sDirName
If Dir(folder$, vbDirectory) = "" Then
MsgBox "Не найдена папка «" & folder$ & "»", vbCritical
Exit Sub ' выход, если папка не найдена
End If
Set coll = FilenamesCollection(folder$, sMask) ' получаем список файлов по маске из папки
If coll.Count = 0 Then
' MsgBox "В папке «" & Split(folder$, "\")(UBound(Split(folder$, "\")) - 1) & "» нет ни одного подходящего файла!", _
vbCritical, "Файлы для обработки не найдены"
Exit Sub ' выход, если нет файлов
End If
Set EX = New Application
EX.Visible = False
' перебираем все найденные файлы
For Each file In coll
Cells(lRow, 2) = CStr(file)
Set wkb = EX.Workbooks.Open(Filename:=file)
' Если книга не пуста
If wkb.Sheets.Count > 0 Then
i = 1
ReDim v(1 To wkb.Sheets.Count)
' Получаем названия листов
For Each wks In wkb.Sheets
v(i) = wks.Name
i = i + 1
Next wks
End If
Cells(lRow, 3) = Join(v, ",")
wkb.Close False
DoEvents
lRow = lRow + 1
DoEvents
Next file
Set wks = Nothing: Set wkb = Nothing: Set EX = Nothing
Set colShts = Nothing
End Sub
Sub LoopThroughDirs()
Dim lLastRow As Long
Dim lRow As Long
Dim i As Long
Dim v As Variant
Dim dTime As Double
lRow = 2
lLastRow = Cells(Rows.Count, 1).End(xlUp).Row
v = Range(Cells(2, 1), Cells(lLastRow, 2))
dTime = Time()
For i = LBound(v) To UBound(v)
Application.StatusBar = "Обрабатывается директория " & i & " из " & UBound(v)
Call LoopThroughFiles(v(i, 1), lRow, "*.xls")
Call LoopThroughFiles(v(i, 1), lRow, "*.xlsx")
Call LoopThroughFiles(v(i, 1), lRow, "*.xlsm")
DoEvents
Next i
MsgBox "Готово за " & CStr(CDate(Time() - dTime))
End Sub
SpreadsheetApp.flush()
. Этот метод останавливает все расчеты и пересчитывает все, что находится у вас в Таблице. Вероятно, из-за него у вас и проблемы.Всё выделяется сразу. Теперь видно с каким диапазоном работаю. Намного более понятно что попадает в значения диапазона.
/**
*
*/
function runOnce() {
trigger_();
}
/**
*
*/
function trigger_() {
try {
triggerAction();
} catch (error) {
console.error(error.message, error);
} finally {
var hours = 10;
var minutes = 17;
var seconds = 56;
var now = new Date();
var nextTime = new Date();
nextTime.setHours(0, 0, 24 * 3600 + hours * 3600 + minutes * 60 + seconds);
var delta = nextTime.getTime() - now.getTime();
ScriptApp.newTrigger('trigger_')
.timeBased()
.after(delta)
.create();
}
}
/**
*
*/
function triggerAction() {
console.log("I'm fine");
}
triggerAction
- это то, что выполняет ваш скриптrunOnce
- это то, что вы должны запустить один раз при первом запуске вашего триггера. Другие настройки не требуютсяtrigger_
- это и триггер и конфигурация вашего триггераUtilities
поддерживали локали.DateTimeFormat
function myFormatDate(date) {
const y = new Intl.DateTimeFormat('ru',{
year: 'numeric'
}).format(date)
const m = new Intl.DateTimeFormat('ru',{
month: 'long'
}).format(date)
return `${m}-${y}`
}
function test(){
const date = new Date();
console.log(Utilities.formatDate(date, "GMT+3", "MMM-yyyy"));
console.log(myFormatDate(date));
}
"MMM-d"
не вернет год - вернет дату. getDisplayValues()
var drr = sheet.getRange(sheet.getLastRow(), 1, 1, 3).getDisplayValues()[0];
0.00%
, то вернет именно 0.00%
, если 1-02-20
, то 1-02-20
.flush()
SpreadsheetApp.flush();
/**
*
* @param {GoogleAppsScript.Events.SheetsOnEdit} e
*/
function onEdit(e) {
var activeSheet = e.source.getActiveSheet();
SpreadsheetApp.getActive().toast(['Лист'].indexOf(activeSheet.getName()));
if (['Лист'].indexOf(activeSheet.getName()) == -1) return;
var r = SpreadsheetApp.getActiveRange();
var cols = r.getColumn();
if (cols == 6) {
// если изменяем 6 колонку, то тригер работает и:
var cell1 = activeSheet.getRange(2, 2); // во второй колонке берет данные из второй строки (там лежит формула)
var destination1 = activeSheet.getRange(activeSheet.getLastRow(), 2); // находит последнюю строку с данными и выбирает вторую колонку
cell1.copyTo(destination1); // копирует из второй строчки в последнюю
var cell2 = activeSheet.getRange(2, 3); // тоже самое но только для 3 колонки
var destination2 = activeSheet.getRange(activeSheet.getLastRow(), 3); // тоже самое но только для 3 колонки
cell2.copyTo(destination2); // тоже самое но только для 3 колонки
var cell3 = activeSheet.getRange(2, 5); // тоже самое но только для 5 колонки
var destination3 = activeSheet.getRange(activeSheet.getLastRow(), 5); // тоже самое но только для 5 колонки
cell3.copyTo(destination3); // тоже самое но только для 5 колонки
var cell4 = activeSheet.getRange(2, 8); // тоже самое но только для 8 колонки
var destination4 = activeSheet.getRange(activeSheet.getLastRow(), 8); // тоже самое но только для 8 колонки
cell4.copyTo(destination4); // тоже самое но только для 8 колонки
SpreadsheetApp.flush();
destination1.copyTo(
destination1,
SpreadsheetApp.CopyPasteType.PASTE_VALUES,
false
); // во второй колонке меняет формулу на значение
destination2.copyTo(
destination2,
SpreadsheetApp.CopyPasteType.PASTE_VALUES,
false
); // в третьей колонке меняет формулу на значение
destination3.copyTo(
destination3,
SpreadsheetApp.CopyPasteType.PASTE_VALUES,
false
); // в пятой колонке меняет формулу на значение
destination4.copyTo(
destination4,
SpreadsheetApp.CopyPasteType.PASTE_VALUES,
false
); // в восьмой колонке меняет формулу на значение
SpreadsheetApp.getActive().toast('Готово');
}
}
var MENU = [
{
caption: 'Пункт меню 1',
functionName: 'itemMenu',
},
{
caption: 'Пункт меню 2',
functionName: 'itemMenu',
},
{
caption: 'Пункт меню 3',
functionName: 'itemMenu',
},
];
function onOpen() {
var ui = SpreadsheetApp.getUi();
var menu = ui.createMenu('Test');
MENU.forEach(function(item, i) {
menu.addItem(item.caption, item.functionName + i);
});
menu.addToUi();
}
itemMenu
работает как-то такfunction itemMenu(e) {
var caption = e.item.caption;
var order = e.order;
Browser.msgBox(
Utilities.formatString('Был нажат %sй пункт меню: %s', order + 1, caption)
);
}
(function(self) {
MENU.forEach(function(item, i) {
self[item.functionName + i] = function() {
return self[item.functionName]({ item: item, order: i });
};
});
})(this);
function onEdit() {
run2();
}
function run2() {
/* Remove dash */
var sheet = SpreadsheetApp.getActiveSheet();
if (sheet.getName() === 'Журнал вода данных') return;
var archive = SpreadsheetApp.getActive().getSheetByName('Журнал вода данных');
var action = function(values, i, i2) {
var data = values.slice(i, i + i2);
archive
.getRange(archive.getLastRow() + 1, 1, data.length, data[0].length)
.setValues(data);
};
var condition = function(values, i) {
var row = values[i];
return (
i > 0 && row[0] !== '' && row[1] !== '' && row[3] !== '' && row[5] !== ''
);
};
deleteRowsByConditional_(sheet, condition, action);
}
function deleteRowsByConditional_(sheet, condition, action) {
sheet
.getDataRange()
.getValues()
.forEach(
function(_, i, arr) {
var j = arr.length - i - 1;
if (this.condition.apply(null, [arr, j])) {
this.isContinue++;
if (j > 0) return;
}
if (this.isContinue > 0) {
var prevPos = j + 1; // It's reversed
if (action) action(arr, prevPos, this.isContinue);
this.sheet.deleteRows(prevPos + 1, this.isContinue);
this.isContinue = 0;
return;
}
return;
},
{ sheet: sheet, condition: condition, isContinue: 0 }
);
}
run2()
к меню.