Страницы: 1 2 След.
RSS
Получение уникального кода для товара
 
Здравствуйте, уважаемые гуру форума и все форумчане! Для возможности проверки остатков мне потребовалось создать некий уникальный код для каждого товара. Так как товар может называться одинаково у разных поставщиков и тем паче у одного и того же поставщика в разных счетах ранее для этого уникального кода я использовал "сцепку" данных (товар|поставщик|документ поставки|дата поставки|цена) такая несколько излишняя проверка гарантировала мне отсутствие повторов. Сейчас я попробовал изменить принцип формирования этого уникального кода товара: просуммировал коды символов всех входящих в "сцепку" символов. Сделал это так:
Код
For i = 1 To Len("проба")
ind = ind + Asc(Mid(UCase("проба"), i, 1))
Next i
ActiveCell = ind
В реальном коде длина преобразованного текста может составить и 50 и 70 символов и вот я хотел бы узнать, можно ли этот код оптимизировать, избавившись от цикла? Скажу сразу, код работает быстро, никаких тормозов не замечаю, вопрос чисто теоретический, для знаний
 
Здравствуйте.
А разве полученный таким способом код будет уникальным?
Например суммы кодов символов в словах  "роза" и "Азор" - совпадут..
Всё сложное - не нужно. Всё нужное - просто /М. Т. Калашников/
 
Цитата
Михаил Лебедев написал:
суммы кодов символов в словах  "роза" и "Азор" - совпадут..
Согласен, и сам уже успел увидеть в реальном файле :oops: . Получается, мне нужно получить код всей "сцепки" разом (сцепка, повторюсь, будет всегда уникальна). Интересно, такое возможно? Или придется похоронить эту идею :(  
 
Цитата
OlegO написал:
Или придется похоронить эту идею  
А в чем собственно идея этого кода? Чем сцепка не устраивает?
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Nordheim написал:
Чем сцепка не устраивает?
Не поверите, просто пытаюсь сделать иначе, фактически для эстетики :D . На текущий момент проверяю следующий вариант (вроде работает без вышеуказанных ошибок):
Код
For i = 1 To Len("проба") Step 2
ind1 = ind1 + Asc(Mid(UCase("проба"), i, 1))
Next i

For i = 2 To Len("проба") Step 2
ind2 = ind2 + Asc(Mid(UCase("проба"), i, 1))
Next i

ActiveCell = ind1 + ind2

Как мне кажется, вероятность того что сумма кодов 1,3,5 ... и 2,4,6... символов совпадет ничтожна. (прошу учесть, что в реальном файле длина склейки ~>50 символов.

НО все-таки, вопрос остается, возможно ли получить подобный УНИКАЛЬНЫЙ код иным образом, без циклов?

 

Изменено: OlegO - 15.10.2018 15:00:49
 
Цитата
OlegO написал:
НО все-таки, вопрос остается, возможно ли получить подобный УНИКАЛЬНЫЙ код иным образом, без циклов?
На счет эстетики понял, а чем циклы не устраивают?
"Все гениальное просто, а все простое гениально!!!"
 
И опять же, просто для знания. Предположим что длина сцепки составляла бы несколько тысяч символов (чисто теоретически) неужели пришлось бы перебирать циклом все название? Вот я и хочу узнать можно ли обойтись без сцепки, получив каким либо образом код сразу для всей сцепки? Если нет значит нет, останется текущий вариант
Изменено: OlegO - 15.10.2018 16:26:03
 
Мне кажется если бы это было возможно то так же циклом, только цикл был бы "зашит" в библиотеке dll и визуально в коде мы бы его (цикл) не видели.
Даже если будет пробегать по тысяче символов (что маловероятно), то не думаю что это будет сильно заметно на скорости работы программы.
А для эстетики запилите функцию в модуль класса  и сделайте переменную для обращения к этой функции (передавая строку обработки параметром) , функция Вам вернет уже готовый код, для эстетики кода макроса самое оно, все как Вы хотели, в коде цикла не видно, а что там где-то, можно и не смотреть.  :D
Изменено: Nordheim - 15.10.2018 16:36:27
"Все гениальное просто, а все простое гениально!!!"
 
Ясно, тему можно считать закрытой (если конечно у кого либо не другой точки зрения) . всем спасибо за внимание
 
OlegO, не спешите закрывать тему. Могу подсказать вариант который может избавить от совпадения Розы и Азора. Можно код на нечётной позиции оставлять как есть, а на чётной умножать на три.
Не стреляйте в тапера - он играет как может.
 
При этом все описанное делается в 1 цикле или в 2-х? Если в 2, то я думаю , что Ваша идея не отличается от моей в 5 сообщении. Ведь какая собственно разница, просто четные позиции или четные позиции *3. А вот если Вы покажете как Ваше предложение сделать за один цикл, то это будет красивее и оптимизированеё наверное, интересно бы взглянуть
 
OlegO, да, принцип тот же, но действительно Вы зря использовали там два цикла
вот вариант кода UDF для варианта предложенного мной
Код
Function Unic_Code(InTxt As String) As Long
    Unic_Code = 0
    InTxt = UCase("InTxt")
    Dim i As Long
    For i = 1 To Len("InTxt")
        If i / 2 = Int(i / 2) Then
                Unic_Code = Unic_Code + Asc(Mid(InTxt, i, 1)) * 3
            Else
                Unic_Code = Unic_Code + Asc(Mid(InTxt, i, 1))
        End If
    Next i
End Function
Извините, но сейчас более трезвым взглядом посмотрел Ваш код в №5, но не понял вообще в нём смыла. Если бы Вам нужен был бы строковый код, то да, а так как Вы хотите получить число, то следуя Вашему коду Вы сначала получите сумму чётных позиций, а потом сумму нечётных, а потом их просуммируете, но насколько я помню арифметику первого класса, там говорили, что от перемены мест слагаемых сумма не меняется.
Изменено: Ts.Soft - 15.10.2018 20:36:00
Не стреляйте в тапера - он играет как может.
 
Может проще брать хэш? Готовые функции есть, результат уникален, и не особо длинный, правда не знаю как будет по ресурсам, да и вид у него посложнее одного числа.
Ну а сумма вряд ли будет уникальной - вот сколько у Вас товаров?
Изменено: Hugo - 15.10.2018 21:12:41
 
СпасибоTs.Soft обязательно проверю на работе Ваш вариант. Hugo, лист прихода в реальном файле рассчитан у меня на 50000 строк, склад небольшой. А по поводу Вашего предложения, не могли ли бы Вы привести примир кода?
 
Цитата
Ts.Soft написал:
более трезвым взглядом посмотрел Ваш код
Сегодня сам более пристально посмотрел на свой вчерашний код и, как мне кажется, понял следующее: такая ситуация может возникнуть только при палиндроме роза-азор, тогда да, хоть как складывай или перемножай числа - не поможет. В произвольном тексте "склейки" вероятность совпадения суммы кодов символов есть (что я сам заметил в реальном файле, действительно и 2+98=100 и 45+55=100), но вот вероятность того что сумма нечетных символов * сумму четных совпадет наверное гораздо ниже? (по крайней мере при первых проверках в реальном файле повторов не выявлено). Тем не менее думать продолжу, Вашу функцию проверю, идею от глубокоуважаемого Hugo тоже попытаюсь проверить (наметки в  сети нашел)
 
OlegO, Может стоит попробовать умножать символы на число используя функцию
Код
RND()

как вариант

Код
Sub test()
    Dim i&, ind&
    Randomize
    For i = 1 To Len("проба")
        ind = ind + Asc(Mid(UCase("проба"), i, 1)) * CDbl(Rnd() * 1000)
    Next i
    ActiveCell = ind
 End Sub

думаю в этом случае вероятность если и есть то минимальна. Да и у Вас получится полноценный ID
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim, но тогда проблема в том что у слова "проба" в первой строке и у слова "проба" во второй строке будут разные ID
Не стреляйте в тапера - он играет как может.
 
Цитата
Ts.Soft написал:
слова "проба" в первой строке и у слова "проба"
На сколько я понял автора совпадений в таблице нет, а вот сумма может совпасть , вроде как с этим пытаемся бороться (ну и с циклами). По идее второй строки с "проба", быть вообще не должно. А если повторения есть, то это просто тупик  8-0. Можно добавить проверку самого значения сцепки через словарь (коллекцию), на случай повтора, но это уже совсем танцы с бубнами.  :D
Изменено: Nordheim - 16.10.2018 09:09:25
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
OlegO написал:
не могли ли бы Вы привести примир кода?
Берите любую функцию отсюда: https://en.wikibooks.org/wiki/Visual_Basic_for_Applications/String_Hashing_in_VBA­
Параметр bB64=True дает более короткую строку.
Изменено: Казанский - 16.10.2018 09:51:34 (исправил ссылку)
 
Алексей, ссылка поплыла...
String_Hashing_in_VBA
 
Цитата
Nordheim написал:
Может стоит попробовать умножать символы на число используя функцию RND()
Я думал о таком варианте, но вот в чем дело. Повторов в сцепках действительно не может быть, но мне в дальнейшем требуется возможность обратной проверки, где в качестве ключа для словаря будет использоваться полученный индекс. Если мы получаем этот индекс каким либо, но четко прописанным способом, то мы можем проверить правильность данных, используя данные листа прихода, а вот если задействовать генератор случайных чисел, то он в следующий раз, для той же строки прихода сформирует новый код, ведь так?
 
OlegO, особо не вникал…
Использование сцепки информации по полям в качестве уникального ключа крайне неэффективно (сам довольно долго использовал этот вариант), поскольку, при любом изменении информации, обновлённый ключ уже будет недействителен, если его "старая версия" была использована где-то ещё. Кроме всего прочего, сцепка даёт очень длинные ключи, а при длине ключа более 255 символов уже ВПРить будет не так-то просто, да и времени займёт на порядок больше.

Для себя я использую эту функцию. Бонусом является тот факт, что потом можно узнать дату и время получения каждого ключа (если вдруг понадобится)
Изменено: Jack Famous - 16.10.2018 10:58:39
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
OlegO написал:
то он в следующий раз, для той же строки прихода сформирует новый код, ведь так?
Совершенно верно. Дело в том что не зная всего алгоритма формирования файлов и дальнейшей работы с ними сложно придумать универсальную функцию присвоения ID.
И по ходу дела всплывают все новые нюансы.  :D. На сколько я понимаю, после того как сформировался ID, может появится такой новый файл, который нужно сверить с уже с уже существующим как раз по ID, а не заморачиваясь сцепкой? И в новом файле ID ,будет формироваться по тому же алгоритму , что и в первом?
Изменено: Nordheim - 16.10.2018 11:14:13
"Все гениальное просто, а все простое гениально!!!"
 
Как вариант, это умножать на счетчик, т.е. как то так:
Код
Sub test()
    Dim i&, ind&
    Randomize
    For i = 1 To Len("проба")
        ind = ind + Asc(Mid(UCase("проба"), i, 1)) * i
    Next i
    ActiveCell = ind
 End Sub

Вероятность совпадения есть но тоже вроде минимальна. Единственное проблема (если это важно), то ID будут различаться количеством символов.
"Все гениальное просто, а все простое гениально!!!"
 
Jack Famous, Вашу идею обязательно проверю
Hugo, что то уж больно длинные и страшные с виду хеши получаются, если воспользоваться Вашей ссылкой 8-0
Выношу на суд уважаемых форумчан 2 варианта функции для хеширования строки, найденные на просторах сети:
Код
Function Hash4(txt)
Dim x As Long, mask, i, j, nC, c As String
Dim crc As Integer, cr2 As Integer, cr3 As Integer ' переменные цикла, которые будут модифицироваться

crc = &HFFFF

For nC = 1 To Len(txt)
    j = Asc(Mid(txt, nC))
    
    ' модификация
    crc = crc Xor j
    cr2 = cr2 Xor crc
    cr3 = cr3 Xor cr2 '(j Xor &H7FFB)
    
    ' применение маскирования к одной из переменных цикла без этого частенько будем получать значния с нулями в начале
    For j = 1 To 8
        mask = 0
        If crc / 2 <> Int(crc / 2) Then mask = &HA001
        crc = Int(crc / 2) And &H7FFF
        crc = crc Xor mask
    Next j
Next nC

' теперь необходимо каждое значение превратить в строку функция Hex$() может вернуть и меньше 4 знаков текста, _
 тогда при склеивании мы рискуем получить ненужные коллизии: A0 & B0 = A & 0B0 .. или что-то в этом роде _
 можно конечно использовать  с = Hex$(crc) + "." + Hex$(cr2) + "." + Hex$(cr3), но это не этстетично

c = Hex$(cr3)
While Len(c) < 4
  c = "0" & c
Wend

c = Hex$(cr2) & c
While Len(c) < 8
  c = "0" & c
Wend

c = Hex$(crc) & c
While Len(c) < 12
  c = "0" & c
Wend

Hash4 = c

End Function
Код
Public Function BASE64SHA1(ByVal sTextToHash As String)
    Dim asc As Object, enc As Object, TextToHash() As Byte, SharedSecretKey() As Byte, bytes() As Byte
    Const cutoff As Integer = 5
        Set asc = CreateObject("System.Text.UTF8Encoding")
        Set enc = CreateObject("System.Security.Cryptography.HMACSHA1")
            TextToHash = asc.GetBytes_4(sTextToHash)
            SharedSecretKey = asc.GetBytes_4(sTextToHash)
            enc.Key = SharedSecretKey
            bytes = enc.ComputeHash_2((TextToHash))
            BASE64SHA1 = EncodeBase64(bytes)
            BASE64SHA1 = Left(BASE64SHA1, cutoff)
        Set asc = Nothing
        Set enc = Nothing
End Function

Private Function EncodeBase64(ByRef arrData() As Byte) As String
    Dim objXML As Object, objNode As Object
        Set objXML = CreateObject("MSXML2.DOMDocument")
        Set objNode = objXML.createElement("b64")
            objNode.DataType = "bin.base64"
            objNode.nodeTypedValue = arrData
            EncodeBase64 = objNode.Text
        Set objNode = Nothing
        Set objXML = Nothing
End Function
Как Вы думаете, какое решение более оптимальное с точки зрения программирования? Требуется квалифицированное мнение гуру :D  
 
Цитата
OlegO: функции для хеширования строки
может в этой моей закладке найдёте что-то более близкое теме…
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Nordheim написал:
Вероятность совпадения есть но тоже вроде минимальна.
К сожалению это не так, в реальном файле на ~ 3000 строк "склеек" совпадений было несколько десятков (я в дополнение в Вашей версии и шаг цикла менял на 2 - не помогло, все равно совпадения есть :( ) Наверное все-таки придется остановиться на хешах, надо проверять . А по поводу Вашего последнего предложения, не могли ли бы Вы взглянуть на предложение в посте №6, почему то VBA ругается на  строку 66?  методом тыка исправить не получается 8-0  
 
Цитата
OlegO написал:
К сожалению это не так, в реальном файле на ~ 3000 строк "склеек" совпадений было несколько десятков
т.е. при умножении на счетчик есть совпадения?
Цитата
OlegO написал:
взглянуть на предложение в посте №6
на что там смотреть , в этом посте только текст. и Можно реальный файл пример с совпадениями.
Изменено: Nordheim - 16.10.2018 14:21:20
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Nordheim написал:
в этом посте только текст.
Ругается на строку 66 и все тут 8-0 , а файл с примером совпадений сейчас подготовлю
 
Цитата
OlegO написал:
Ругается на строку 66 и все тут  
У меня в посте 6 всего две строки, одна из них цитата. там нет ни кода ни строки 66
"Все гениальное просто, а все простое гениально!!!"
Страницы: 1 2 След.
Наверх