УПС! или испанский стыд...

Автор Злоп, 27 октября 2024, 23:40

« назад - далее »

Злоп

Это коллектор всяких приключений, косяков, неожиданностей, провалов и прочего испанского стыда приключившегося...

Злоп

С ТЗ еще есть прикол, что можно несколько колонок с одинаковым Идентификатором вкорячить... А потом сидишь колупаешься что за хрень.. Пока не визуализируешь.. ;-)

Злоп

Как-то я потратил часа два, если не больше:
Трабл, не отрабатывает ПриОткрытии()
Я уже и так и сяк, и в миссионерской позе и по-собачьему.
Но не выходит каменный цветок!
Не отрабатывает ПриОткрытии() ну хоть ты тресни...
Пока не "покурил".
И ВНЕЗАПНО обнаружил, что

Функция ПриОткрытии()...

Харлампий Дымба

Поддержу тему, просто чтоб Сергею неодиноко было. Опять же - именно для испанского стыда нужны как минимум двое :)

Что-то вот глобальных проколов, слава богу, не припомню. Пару относительно лайтовых:
1. На одной из первых 1сных работ вечерком чистил сервер (если так можно назвать машину с win95) и удалил копию базы db1, оставив рабочую с именем db, я же не знал, что предыдущий 1сник был с параноидальной дуринкой. На следующий день в обед достал её из корзины - и прослыл в бухгалтерии волшебником, спасшим базу.
2. Когда-то научил продвинутую бухшу, работавшую со многими на аутсорсе, обходу авторизации через USRDEF0, чтоб ей присланные базы без проблем открывать. Она воспользовалась советом стукнувшись ночью по rdp к рабочей базе своего нового клиента - крупного поставщика автозапчастей. А база была в SQL. Подключение к базе само собой слетело, но вроде обошлось без жертв: прогер на следующий день базу подключил обратно (наверное, тоже прослыл волшебником, спасшим базу).

Из тех что касается себя:
Ковыряешь день какой-нибудь отчет, предварительно выгрузив его во внешний, потом ПКМ на исходном отчете и вместо "Заменить на внешний отчет" щёлкаешь "Сохранить как внешний отчет" и затираешь все изменения. Обидно.
То же самое - но только через двойное редактирование в разных конфигураторах - открываешь внешний отчет в рабочей базе, потом переходишь для отладки в копию базы, там доводишь очет и сохраняешь, а потом нечаянно повторно сохраняешь в конфигураторе рабочей базы, выкинув в помойку всю работу.

Что касается языка, то у каждого, наверное, за эти годы уже есть какие-то флажки: "тут внимательно - был негативный опыт".
Немного моих:
\ - контролируй делений на ноль;
+ - хочешь получить строку, следи за первым операндом;
всегда учитывай есть ли УРБД;
всегда учитывай состав компонент (типа не используй объект Календарь, если не уверен что будет компонента "Расчет")
храни и вызывай внешние dll в одном месте (каталог программы, а не каталог базы данных), чтобы избежать проблем с правами на регистрацию компонент;
используй только необходимое;
при удаление/изменении - помни про указатель и порядок выборки;
для глобальной переменной считывание реквизитов из базы выполняется при присвоении - осторожно;

Если Иначе КонецЕсли - логические выражения проверяются полностью;
Окр() - всегда указывай способ округления, всегда учитывай точность результата, при распределении суммы по базе не забывай про оставшиеся копейки;
Строка() - преобразование документа в строку идёт с датой/без даты в зависимости от уникальности нумерации, при работе со строками (особенно обмены между базами) помни про многострочность и запрещенные символы;
Дата - указывать год полностью '18.11.2024' (год начала рабочего столетия), не путай двойные кавычки и одинарные;
Формат() - "ДДММГГГ", "Д (0)ДДММГГ", "Д ДДММММГГ" и прочие неправильные форматные строки - молча вхолостую отрабатывает, не меняя вывод;
Найти() - не путай порядок параметров, результат >0, а не =1
Состояние() - не преобразует агрегатные объекты к пользовательскому представлению: Состояние(Спр.ТекущийЭлемент()) - неправильно;
Каталогиб() и прочие возвращающие пути - по разному работали в разных ОС (в win95 не добавлялся последний слеш) - уже неактуально;
ИмяКомпьютера() - для терминального подключения вернёт имя сервера;
НачатьТранзакцию() - не забыть Зафиксировать или Отменить, с Попытка дружит плохо (или не дружит?), запись изменений делать подобранными порцями;
ЗначениеВСтрокуВнутр и ЗначениеВСтроку - не путать между собой и особенно при восстановлении значений через ЗначениеИзСтрокиВнутр и ЗначениеИзСтроки;
СтатусВозврата - смотри где используешь, если надо, а как правило - надо, то делай после него Возврат;
ПустоеЗначение и ПолучитьПустоеЗначение - не путай;
ПустоеЗначение() возвращает ноль для битых ссылок - используй Выбран()=1 для дополнительной проверки (замедляет);
ЗаписьЖурналаРегистрации - старайся использовать при программных изменениях объектов;
УдалитьОбъекты - может падать на больших количествах - удаляй порциями;
ОткрытьФорму - используй при необходимости #;
ПриОтменеПроведенияДокумента() - не вызывается при пометке документа на удаление (хотя ИТС считает иначе, и в частности поэтому в ЗиК была историческая проблема с созданием дублирующих записей-перерасчетов, попившая крови многим);
ПриУдаленииЭлемента(), ПриУдаленииДокумента() - вызывается также и при отмене удаления, так что надо контролировать состояние на момент вызова, при удалении группы и подчиненных вызывается единожды для всех сразу;
ИспользоватьСлой() - после переключения видимости слоя туда-сюда Видимость()=1
Не называй реквизиты формы на "я";
Не именуй реквизиты формы, атрибуты справочников и переменные одинково;

Справочники:
Родитель и ИспользоватьРодителя(), Владелец и ИспользоватьВладельца() - не путай
Получить(),Установить() и ИспользоватьДату() - осторожно, для работы в формах используй лучше Получить(), в отчетах и обработках - что удобно;
ИспользоватьДату() - не забывай про параметр УстСразу;
Установить() - работает без Записать();
получить() и установить() через 2 точки работает на последних релизах;
Уровень() - для верхнего уровня возвращает 1;
УстановитьАтрибут(), ПолучитьАтрибут(), а также присвоение и получение атрибутов справочника - молча вхолостую  отрабатывает для групп атрибуты с режимом использования "Для элементы", а для элементов - с режимом использования "Для групп";
НайтиПоКоду() - если код числовой, можно передать строкой;
ВыбратьЭлементыПоРеквзитиу () - про это писал отдельно;
ОбратныйПорядок() - используй до выборки, не забывай указать параметр Режим;
Записать - если меняешь реквизиты в выборке, то используй ПорядокКодов, ПорядокНаименований, ПорядокРеквизита, а также иерархию, которые не затрагивают измененяемые реквизиты;
Удалить(1) - не используй / используй осознано
Блокировка() - возвращает состояние блокировки для ТЕКУЩЕГО пользователя, особый режим использования;
Записать(), Удалить(), СнятьПометкуУдаления(), ПометкаУдаления() - контролируй возможность блокировки другим пользователем;
Программное Записать() не вызывает ПриЗаписи() и т.д.;
ИспользоватьСписокОбъектов() - отключай иерархию или контролируй владельца/родителя, + не будет работать быстрый поиск по строке;
ПриВводеСтроки, ПриРедактированииНовойСтроки, ПриНачалеРедактированияСтроки - не путай, писал про это;
Редактирование в форме списка использовать осознано - есть ряд особенностей, писал про это;
в ПриОткрытии и прочем таком - присваивай значения атрибутам, только если они меняются, чтобы у пользователя ненужная Модифицированность не возникала;
Не путай объект и ссылку на объект;

Документы:
Многое подобно справочникам и плюс:
Документ.Операция - если не знаешь точно, сначала вызывай .СуществуетОперация();
Новый() - если меняешь / устанавливаешь дату - контролируй номер;
ПриЗаписиПерепроводить(1) - не забывай;
УстановитьВремя() - работает после АвтоВремяОтключить(), вызывать во ВводНового();
Не уверен в работе .Провести() без предварительного .Записать();
УстановитьРеквизитСправочника() с указанием документа будет позже, чем ручная или программная (через .Установить) запись в этот же день, значения за одну дату устанвливаются по порядку документов;
ОбработкаУдаленияПроведения не вызывается при перепроведении;
ПривязыватьСтроку - работает для расчета, регистров, периодических значений - если привязываешь строки, то зануляй привязку в конце (иначе при групповом перепроведении может вылезти в чужих документах?);

СписокЗначений:
Не путай НайтиЗначение и Принадлежит, и вообще не используй Принадлежит без особой надобности (тормоза);
вСтрокуСРазделителями - если в списке есть многострочные строки, то результат тоже будет многострочным (внимательно при обменах);

ТаблицаЗначений - тут много всего, надо будет поразбираться как-нибудь:
НомерСтроки и ТекущаяСтрока() - не путай
НоваяКолонка - для чисел указывай тип явно, иначе Свернуть() не будет правильно суммировать колонки, в котороых есть пустые ячейки (где явно не задано значение 0);
НоваяКолонка - если задашь несуществующий тип  (опечатка, например) - молча отработает;
НайтиЗначение - параметры Строка и Колонка если указаны, то поиск идёт только в указанной строке/колонке, так что зануляй Строка (или Колонка) перед поиском.
Выгрузить/Загрузить - не сохраняет значения установленные ВидимостьКолонки,  ВыводитьПиктограммы, Фиксировать
Сортировать - пользуйся *;
Сортировать - помни про Параметр ДокумПоДате;
Сортировать - баг, после сортировки нельзя использовать КоличествоСтрок(), СдвинутьСтроку() и что-то ещё, вроде писал про это;
Заполнить - используй только в  обёртке Если .Количестовстрок()>0;
Если кладешь СписокЗначений/ТаблицуЗначений в СписокЗначений/ТаблицуЗначений для каждой новой строки делай СоздатьОбъект();

Таблица:
КоличествоСтраниц - работает долго, + нужен контроль релиза
ВывестиСекцию или Область - проигрывают ПолучитьСекцию();
Напечатать  - длина имени принтера максимум 31 символ (-20 на русский _Перенаправлено ХХ) = 11 символов;

Не, не осилил.







trdm

Цитата: Харлампий Дымба от 18 ноября 2024, 17:33Из тех что касается себя:
Ковыряешь день какой-нибудь отчет, предварительно выгрузив его во внешний, потом ПКМ на исходном отчете и вместо "Заменить на внешний отчет" щёлкаешь "Сохранить как внешний отчет" и затираешь все изменения. Обидно.
То же самое - но только через двойное редактирование в разных конфигураторах - открываешь внешний отчет в рабочей базе, потом переходишь для отладки в копию базы, там доводишь очет и сохраняешь, а потом нечаянно повторно сохраняешь в конфигураторе рабочей базы, выкинув в помойку всю работу.
У меня скрипт работает, который при сейве внешнего отчета кидает его копию в ExtForms\_Arhive
 

Arbuz

Цитата: trdm от 19 ноября 2024, 10:41У меня скрипт работает, который при сейве внешнего отчета кидает его копию в ExtForms\_Arhive
 

Я его слегка подпилил и он сохраняет и мд'шки в .\_Arhive
Каталог правда пухнет интенсивно.
Спасибо — очень нужная штука, несколько раз выручало.

Харлампий Дымба

Цитата: trdm от 19 ноября 2024, 10:41У меня скрипт работает, который при сейве внешнего отчета кидает его копию в ExtForms\_Arhive
Хорошее решение, если рабочее место постоянно. Но если подключаешься к эпизодическому заказчику, не всегда получается принести своё окружение с собой. Я и попытался перечислить некоторые свои триггеры и правила по ним: "включаешь отчет в конфу - обрати внимание", "не держи 2 конфигуратора для редактирования", ну и тд. Ну и такие проколы с сохранением уже и не вспомню когда случались, значит правила работают, тьфу 3 раза.
А что за скрипт, если не секрет?

Arbuz

Я так понимаю, что это изначально ИсторияОткрытияДокументов.vbs для OpenConf, в который trdm в 21 году добавил сохранение копий внешних отчётов. В который я, в свою очередь, прикрутил сохранение копий мд'шек.
'ИсторияОткрытияДокументов.vbs
'(c) trdm 2006
Dim DictHWND : Set DictHWND = CreateObject("Scripting.Dictionary")
Dim DictCPTN : Set DictCPTN = CreateObject("Scripting.Dictionary")

Dim strFilePath

'+
' trdm 2021-03-19 04:17:29
' Делает копию файла после сохранения в конфигураторе.
' Работает только с файлами в  в каталоге 'IBDir + "ExtForms\"'
Sub makeCopyToArhive(psDocPath)
    Set FSO = CreateObject("Scripting.FileSystemObject")
    vCopyFolder = IBDir + "ExtForms\_Arhive\"
    vCheckFolder = IBDir + "ExtForms\"
    vDocPathNew = psDocPath
    'message vDocPathNew
    'message vCheckFolder
    if InStr(1,psDocPath,vCheckFolder,1) = 0 Then
        if Left(psDocPath, 1) <> "\" Then
        message "not in ExtForms, not backup"
    end if
        exit sub
    Else
        vDocPathNew = Replace(vDocPathNew,vCheckFolder,"",1,-1,1)
        vDocPathNew = Replace(vDocPathNew,"\","#")

    end if
    'message vDocPathNew
    if not FSO.FolderExists(vCopyFolder) Then
        exit sub
    end if
    str_now = CStr(Now)
    str_date = Left(str_now,10)
    str_time = Right(str_now,8)
    str_nowA = Split(str_date,".")
    str_nowB = Split(str_time,":")
    vDocPathNew = "" + str_nowA(2)+str_nowA(1)+str_nowA(0)+"_"+str_nowB(0)+str_nowB(1)+str_nowB(2)+"_" + vDocPathNew
    vDocPathNew = vCopyFolder + vDocPathNew
    FSO.CopyFile psDocPath,vDocPathNew
End Sub


Private Sub RegisterOpenWindow( spDoc, sOpt)
'Stop

    Set FSO = CreateObject("Scripting.FileSystemObject")
    if Not FSO.FileExists(strFilePath) Then
        Set TextStream = FSO.CreateTextFile(strFilePath,false)
        TextStream.Close
    End If
    Set File = FSO.GetFile(strFilePath)
    Set TextStream = File.OpenAsTextStream(8,0)

    If isObject(spDoc) Then
        strToWrite = FormatDateTime(now(),0) +" "+spDoc.Name
        strToWrite = Replace(strToWrite,"CBodyTextDoc::","")
        strToWrite = Replace(strToWrite,"CSheetDoc::","")
        strToWrite = Replace(strToWrite,"CWorkBookDoc::","")
    Else
        strToWrite = spDoc
    End If

    TextStream.WriteLine sOpt + strToWrite
    TextStream.Close

End Sub

' просто добавим окна в словарь.....
Private Sub RemakeDictHWND(  )
    DictHWND.RemoveAll
    DictCPTN.RemoveAll
    Set w = Windows.FirstWnd
    While Not w Is Nothing
        DictHWND.Add CStr(w.hWnd), w.Caption
        on error resume next
        if Len(w.Document.path)>0 Then    DictCPTN.Add w.Document.path, CStr(w.hWnd)
        on error goto 0
        Set w = Windows.NextWnd(w)
    Wend
End Sub

Private sub RegisterWindow( psWnd, spDoc )
    sHWND = CStr(psWnd.HWND)

    if Not DictHWND.Exists(sHWND) Then
        RegisterOpenWindow spDoc, "find "
    End IF
    RemakeDictHWND
    ' Сохраним HWND-ы всех окон в системе и будем добавлять в лог файл только
    ' те, которых раньше не было....
End Sub

' artbear - устраню ошибку, возникающую при закрытии всех окон (через меню) - если переданное окно уже не существует
' Устанавливает GlobalModuleParse в 0, что означает, что мы не парсили Глоб. модуль
'  или побывали в нем, значит возможно он изменен и придется его
' еще раз отпарсить.
Sub Configurator_OnActivateWindow(Wnd,bActive) 'As ICfgWindow, ByVal bActive As Boolean)
    On Error Resume Next
    Set doc134 = Wnd.Document
    iErrNumber = err.Number
    On Error GoTo 0
    If iErrNumber <> 0 Then
      Exit Sub
    End If

    if Not bActive Then
        Exit Sub
    End IF
    on error resume next
    iErrNumber = Err.Number
    on error goto 0
    Set doc = Wnd.Document

    if doc.Type = 0 Then
        Exit Sub
    End IF
    RegisterWindow  Wnd, doc
End Sub

Sub Configurator_OnFileSaved( psDoc )
    ' trdm 2021-03-19 03:48:36
    'Message psDoc.path
    makeCopyToArhive psDoc.path
    if Not DictHWND.Exists(psDoc.path) Then
        RegisterOpenWindow psDoc, "save "
    End IF
    RemakeDictHWND
End Sub

Sub Configurator_MetaDataSaved(FileName)

  Set fso = CreateObject("Scripting.FileSystemObject")

      path = fso.GetParentFolderName(FileName)

  path = LCase(path)

      If InStr(path, "new_stru") <> 0 Then
          path = fso.GetParentFolderName(path)
      End If

    fname = "1cv7.md"
    vCopyFolder = path+"\_Arhive\"
    if not FSO.FolderExists(vCopyFolder) Then
        exit sub
    end if
    str_now = CStr(Now)
    str_date = Left(str_now,10)
    str_time = Right(str_now,8)
    str_nowA = Split(str_date,".")
    str_nowB = Split(str_time,":")
    vDocPathNew = "" + str_nowA(2)+str_nowA(1)+str_nowA(0)+"_"+str_nowB(0)+str_nowB(1)+str_nowB(2)+"_" + fname
    vDocPathNew = vCopyFolder + vDocPathNew
    RegisterOpenWindow vDocPathNew, "save "

End Sub

Sub OpenHistory()
    Documents.Open(strFilePath)
End Sub

Sub InitScript()
'Stop
    strFilePath = IBDir+"_HistoryDocs.txt"
    str_now = CStr(Now)
    str_now = Left(str_now,10)
    str_nowA = Split(str_now,".")
    strFilePath = IBDir+""+str_nowA(2)+"_"+str_nowA(1)+"_HistoryDocs.txt"


End Sub

InitScript

PS: раскраску бы для vbs

Харлампий Дымба

А вот испанский стыд с Селезнёвки подоспел, новое поколение обнаружило:
Цитата: Харлампий Дымба от 18 ноября 2024, 17:33при распределении суммы по базе не забывай про оставшиеся копейки;
и пытается победить копейки:
https://buh.ru/articles/novyy-algoritm-spisaniya-dopolnitelnykh-raskhodov-pri-vedenii-razdelnogo-ucheta-nds-v-1s-bukhgalteri.html
Если коротко: как я понял,в типовой БП при списании стоимости МПЗ определяли сумму поступивших доп.расходов, приходящихся на списываемое, в разрезе документов поступления этих доп.расходов, пропорционально списанию.
То есть приход партии товаров, приход доп.расходов к этой партии несколькими документами, частичное списание товара - надо частично списать долю доп.расходов в разрезе документов поступления. Не смогли победить копейки. ???
Тупо сделали для всех с 01.10.2024 списание доп.расходов по FIFO.
Я, конечно, 8ку в руках не держал, но если у ребят, пишущих типовую с такой ерундой проблемы, то пожалуй и не подержу.

Ну вот же в типовой бухии 7.7:
Процедура глРаспределитьПропорционально(ИсхСумма, ТабличнаяЧасть, КолонкаОснование, КолонкаРаспределения, ЗнаковОкругления = 2) Экспорт

	ИтогПоОснованию = ТабличнаяЧасть.Итог(КолонкаОснование);
	
	Если ИсхСумма=ИтогПоОснованию Тогда
		Для К = 1 По ТабличнаяЧасть.КоличествоСтрок() Цикл
			ТабличнаяЧасть.УстановитьЗначение(К, КолонкаРаспределения, ТабличнаяЧасть.ПолучитьЗначение(К, КолонкаОснование));
		КонецЦикла;
		Возврат;
	КонецЕсли;	
		
	Если ИтогПоОснованию = 0 Тогда
		Возврат;
	КонецЕсли;
	
	МаксЗнач	= 0;
	ИндексМакс	= 0;
	Для К = 1 По ТабличнаяЧасть.КоличествоСтрок() Цикл
		ТекЗнач		= ТабличнаяЧасть.ПолучитьЗначение(К, КолонкаОснование);
		МодульЧисла = ?(ТекЗнач > 0, ТекЗнач, -ТекЗнач);
		Если МаксЗнач < МодульЧисла Тогда
			МаксЗнач	= МодульЧисла;
			ИндексМакс	= К;
		КонецЕсли;
		УстанавливаемоеЗначение = Окр(ИсхСумма * ТекЗнач / ИтогПоОснованию, ЗнаковОкругления, 1);
		ТабличнаяЧасть.УстановитьЗначение(К, КолонкаРаспределения, УстанавливаемоеЗначение);
	КонецЦикла;
	
	ИтогПоРаспределению = ТабличнаяЧасть.Итог(КолонкаРаспределения);
	Если ИсхСумма <> ИтогПоРаспределению Тогда
		УстанавливаемоеЗначение = ТабличнаяЧасть.ПолучитьЗначение(ИндексМакс, КолонкаРаспределения)
									+ ИсхСумма - ИтогПоРаспределению;
		ТабличнаяЧасть.УстановитьЗначение(ИндексМакс, КолонкаРаспределения, УстанавливаемоеЗначение);
	КонецЕсли;
	
КонецПроцедуры // глРаспределитьПропорционально()

Злоп

Для копий внешних обработок у меня стоит патч Ромикса, спасал неоднократно.