1Cでデータを扱うことは、本質的にコレクションを常に扱うことです。ディレクトリ、ドキュメント、レジスタはすべて、並べ替え、フィルタリング、変換する必要があるデータ配列です。サイクルを理解しなければ、真剣な処理を書くことはできません。この記事では、1Cのすべてのタイプのループを分析し、実際の例を示し、ドキュメントが沈黙している落とし穴について説明します。

3つの鯨:1Cのサイクルの種類
1C: Enterpriseプラットフォームには、サイクルを編成するための3つのデザインがあります。それぞれが独自のシナリオに合わせて調整されています。
「For」ループ:反復回数がわかっている場合
従来のカウントループ。アクションを実行する必要がある回数が事前にわかっている場合に使用されます。
Для Счетчик = 1 По 10 Цикл
Сообщить("Iteration No." + Счетчик);
КонецЦикла;重要なニュアンス:カウンター変数は、各反復の後に自動的に1ずつ増加します。1Cでは、他の言語のように任意のステップを設定することはできません。1 以外のステップが必要な場合は、次のようにする必要があります。
Для Индекс = 0 По 9 Цикл
РеальныйШаг = Индекс * 3;
Сообщить("Value: " + РеальныйШаг);
КонецЦикла;典型的なシナリオは、インデックスで配列を反復することです。
МассивТоваров = Новый Массив;
МассивТоваров.Добавить("Laptop");
МассивТоваров.Добавить("Monitor");
МассивТоваров.Добавить("Keyboard");
Для Инд = 0 По МассивТоваров.ВГраница() Цикл
Сообщить(МассивТоваров[Инд]);
КонецЦикла;「すべての人のために」サイクル — 万能な兵士
1Cで最も人気のあるサイクル。配列、値のリスト、テーブル部分、クエリ結果、構造、マッピングなど、あらゆるコレクションで動作します。
Для Каждого Элемент Из МассивТоваров Цикл
Сообщить(Элемент);
КонецЦикла;主な利点は、インデックス、境界、要素数を考える必要がないことです。単にコレクションの各要素を操作するだけです。
「Poka」ループは、終了条件が事前にわからない場合に使用します。
条件が真である限り実行されます。イテレーション数が事前にわからない状況に最適です。
Остаток = 1000;
Месяц = 0;
Пока Остаток > 0 Цикл
Остаток = Остаток - 150;
Месяц = Месяц + 1;
КонецЦикла;
Сообщить("Funds will run out in " + Месяц + " months");注意してください。条件が決して偽にならない場合、無限ループが発生し、プラットフォームがフリーズします。常に非常口を用意してください。
Счетчик = 0;
Пока НеВыполненоУсловие И Счетчик < 10000 Цикл
// 処理ロジック
Счетчик = Счетчик + 1;
КонецЦикла;
文書の表部分の処理
テーブル部分は、1C 開発者が作業する最も一般的なデータ構造の 1 つです。いくつかの実践的なタスクを見てみましょう。
表の部分の合計を計算する
ИтогоСумма = 0;
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
ИтогоСумма = ИтогоСумма + СтрокаТЧ.Количество * СтрокаТЧ.Цена;
КонецЦикла;
Сообщить("Total amount: " + ИтогоСумма);表部分から行を削除する
ここからが面白いところです。初心者の典型的な間違いは、前方ループで行を削除することです。
// ❌ このような行はスキップしてください。
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
Если СтрокаТЧ.Количество = 0 Тогда
Документ.Товары.Удалить(СтрокаТЧ);
КонецЕсли;
КонецЦикла;行を削除すると、コレクションがシフトし、次の要素が「スリップ」します。正しいアプローチは、表の部分を逆の順序でバイパスすることです。しかし、1Cの標準的な「For」ループはカウントダウンをサポートしていないため、「While」を使用します。
// ✅ 正しい逆パス
Инд = Документ.Товары.Количество() - 1;
Пока Инд >= 0 Цикл
СтрокаТЧ = Документ.Товары[Инд];
Если СтрокаТЧ.Количество = 0 Тогда
Документ.Товары.Удалить(Инд);
КонецЕсли;
Инд = Инд - 1;
КонецЦикла;表形式の部分で重複を検索する
常に発生するタスクは、同じ商品を見つけて統合することです。
Инд = 0;
Пока Инд < Документ.Товары.Количество() Цикл
ТекСтрока = Документ.Товары[Инд];
Инд2 = Инд + 1;
Пока Инд2 < Документ.Товары.Количество() Цикл
СравнСтрока = Документ.Товары[Инд2];
Если ТекСтрока.Номенклатура = СравнСтрока.Номенклатура Тогда
ТекСтрока.Количество = ТекСтрока.Количество + СравнСтрока.Количество;
Документ.Товары.Удалить(Инд2);
Иначе
Инд2 = Инд2 + 1;
КонецЕсли;
КонецЦикла;
Инд = Инд + 1;
КонецЦикла;注意:重複を削除する場合、次の要素がその場所に移動するため、Ind2は増加しません。

クエリからのサンプルの操作
1Cでのクエリの結果は配列ではなく、特別な方法で処理される特別なオブジェクトです。
サンプルの基本的なスキャン
Запрос = Новый Запрос;
Запрос.Текст =
"SELECT
| Nomenclature.Name AS Name,
| Nomenclature.Price AS Price
| FROM | Reference Book.Nomenclature AS Nomenclature
|WHERE
| Nomenclature.Price > 0";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование + ": " + Выборка.Цена + " RUB");
КонецЦикла;メソッド Следующий()は、ポインタを次のレコードに移動し、レコードが存在する場合はИстинаを返します。レコードが終了すると、Ложьが返され、ループが終了します。
階層サンプルのバイパス
階層を持つディレクトリの場合は、グループ化された選択を使用すると便利です。
Результат = Запрос.Выполнить();
ВыборкаГруппы = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаГруппы.Следующий() Цикл
Сообщить("== Group: " + ВыборкаГруппы.Категория + " ==");
ВыборкаДетали = ВыборкаГруппы.Выбрать();
Пока ВыборкаДетали.Следующий() Цикл
Сообщить(" " + ВыборкаДетали.Наименование);
КонецЦикла;
КонецЦикла;複数の結果を持つバッチリクエスト
クエリが複数のテーブルを返す場合は、それぞれを処します。
МассивРезультатов = Запрос.ВыполнитьПакет();
Для Каждого РезультатЗапроса Из МассивРезультатов Цикл
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// 行の処理
КонецЦикла;
КонецЦикла;構造とマッチングのスキャン
構造とマッチはキーと値のペアです。それらはДля Каждогоを介してバイパスされます。
Параметры = Новый Структура;
Параметры.Вставить("Organization", "Romashka LLC");
Параметры.Вставить("Period", ТекущаяДата());
Параметры.Вставить("Warehouse", "Primary");
Для Каждого КлючЗначение Из Параметры Цикл
Сообщить(КлючЗначение.Ключ + " = " + КлючЗначение.Значение);
КонецЦикла;マッチングの構文は似ていますが、マッチングでは文字列だけでなく、任意のタイプのキーを許可します。
サイクル管理:中断と再開
2人のオペレーターが、サイクルの進行を柔軟に制御できます。
Прервать — 直ちにループを終了します。
Для Каждого Товар Из Каталог Цикл
Если Товар.Наименование = "Searched product" Тогда
НайденныйТовар = Товар;
Прервать;
КонецЕсли;
КонецЦикла;Продолжитьは、残りの反復コードをスキップして、次の反復に進みます。
Для Каждого Контрагент Из СписокКонтрагентов Цикл
Если Контрагент.ЭтоГруппа Тогда
Продолжить; // グループをスキップします
КонецЕсли;
// 要素のみの処理
ОбработатьКонтрагента(Контрагент);
КонецЦикла;パフォーマンスに関する実用的なヒント
1C で迅速かつ確実なループを記述するのに役立つ規則がいくつかあります。
ループ内でデータベースを参照しないでください。 データベースへの呼び出しはすべてネットワーク要求です。10,000 行ある場合、サーバーに 10,000 回の呼び出しを行います。代わりに、ループの前に1回のクエリですべての必要なデータを取得します。
// ❌ 遅い: ループ内のリクエスト
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
Остаток = РегистрыНакопления.ОстаткиТоваров
.ПолучитьПоследнийСрез(, "Nomenclature = &Nom");
КонецЦикла;
// ✅ 迅速: 1 つのリクエスト、その後のサイクル
Запрос = Новый Запрос;
Запрос.Текст = "SELECT Nomenclature, Remainder FROM ...";
ТаблицаОстатков = Запрос.Выполнить().Выгрузить();
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
НайденнаяСтрока = ТаблицаОстатков.Найти(
СтрокаТЧ.Номенклатура, "Nomenclature");
Если НайденнаяСтрока <> Неопределено Тогда
Остаток = НайденнаяСтрока.Остаток;
КонецЕсли;
КонецЦикла;ネストされたループの代わりに、ValueTable.FindRows () を使用します。 ネストされたループを反復する代わりに、組み込みの検索メソッドを使用します。これらのメソッドは、はるかに高速に動作します。
// ❌ 入れ子のループ O(n²)
Для Каждого Строка1 Из Таблица1 Цикл
Для Каждого Строка2 Из Таблица2 Цикл
Если Строка1.Ключ = Строка2.Ключ Тогда
// ...
КонецЕсли;
КонецЦикла;
КонецЦикла;
// ✅ FindString O(n)による検索
Для Каждого Строка1 Из Таблица1 Цикл
Отбор = Новый Структура("Key", Строка1.Ключ);
НайденныеСтроки = Таблица2.НайтиСтроки(Отбор);
Для Каждого НайдСтрока Из НайденныеСтроки Цикл
// ...
КонецЦикла;
КонецЦикла;大量のデータの場合は、マッチングによるインデックスを使用します。
Индекс = Новый Соответствие;
Для Каждого Строка Из Таблица2 Цикл
Индекс.Вставить(Строка.Ключ, Строка);
КонецЦикла;
Для Каждого Строка1 Из Таблица1 Цикл
НайденнаяСтрока = Индекс.Получить(Строка1.Ключ);
Если НайденнаяСтрока <> Неопределено Тогда
// 見つかった文字列を処理します
КонецЕсли;
КонецЦикла;このテクニックは、O(n²)をO(n)に変換し、何千もの行を処理する際に非常に重要です。
チートシート:どのサイクルを選択しますか?
課題 | サイクル | 理由 |
|---|---|---|
インデックス付き配列の反復 | 宛先… | インデックスによるアクセスが必要です |
表の部分をスキップ | すべての人のために | 最も読まれているバージョン |
コレクションから行を削除する | 今のところ(逆方向) | 要素をスキップしないようにします |
クエリ結果の選択 | 選択中。次へ () | 回避する唯一の方法 |
条件まで繰り返す | 今のところ | 反復回数が不明です |
構造/適合性のスキャン | すべての人のために | キーと値のペアを取得します |
結論
1Cのサイクルは、すべての処理、すべてのレポート、およびすべてのモジュールで使用するツールです。3つの主要なルールを覚えておいてください。ループ内のデータベースに入らないでください。要素を逆の順序で削除し、クイック検索にマッチングを使用してください。これらの3つのテクニックは、初心者の1C開発者と経験豊富な開発者を区別します。
プログラミングを始めたばかりの方や、新しいテクノロジーを習得したい方は、アプリケーションをご覧ください コディックPython、JavaScript、HTML、CSSなどの言語の構造化されたコースがあり、基本を理解して実際のタスクに移行するのに役立ちます。そして私たちの Telegramチャンネル いつでも質問をしたり、2000人以上の開発者からなるコミュニティからサポートを受けたり、新しい資料を入手したりできます。プログラミングは、助けてくれる人がそばにいると、思ったよりも簡単です。
