Перевод строки чисел в Excel - PullRequest
3 голосов
/ 21 февраля 2020

Так что в основном у меня 18 цифр git в одном столбце. Эта строка представляет роль данного человека в этой таблице:

100000000000000000 -> Admin

000000000010000000 -> TL

000000000100000000 -> DEV

000000010000000000 -> Viewer

000000100000000000 -> TE

000000000000100000 -> TA

По длине строки я предполагаю, что они являются более ролями, которые не важны сейчас, но могут быть позже. Проблема в том, что может быть любая комбинация ролей, например:

000000010100000000 -> DEV, Viewer

000000100100000000 -> DEV, TE

100000010000100000 -> Admin, TA, Viewer

Моя задача - перевести каждую строку в роли.

Поскольку я знаю, какая позиция представляет какую роль, я могу просто найдите строку «1» и по позиции «1» добавьте репрезентативные роли. Вот моя проблема, я понятия не имею, если VB предлагает возможность поиска строки для многократного появления данного символа и сохранить их относительные позиции. Если это так, то это только вопрос добавления «если тогда» для каждой роли. Если этого не произойдет, я потерялся, как сейчас.

Ответы [ 6 ]

4 голосов
/ 21 февраля 2020

Еще один код, похожий на тот, что в ответах

Sub Test()
    Dim txt As String
    Dim r As String
    Dim i As Integer
    Dim roles(1 To 13) As String

    txt = "100000010000100000"
    roles(1) = "Admin"
    roles(7) = "TE"
    roles(8) = "Viewer"
    roles(10) = "DEV"
    roles(11) = "TL"
    roles(13) = "TA"

    For i = 1 To Len(txt)
        If Mid(txt, i, 1) = "1" Then r = r & roles(i) & ", "
    Next

    Debug.Print Left(r, Len(r) - 2)
End Sub
4 голосов
/ 21 февраля 2020

Вот один из способов построить свои роли:

Private Sub Test()
   Dim role As String
   Dim roles As String
   Dim i As Integer

   role = "000000010100000000"

   For i = 1 To Len(role)
      If i = 1 And Mid(role, i, 1) = "1" Then roles = roles & "Admin, "
      If i = 7 And Mid(role, i, 1) = "1" Then roles = roles & "TE, "
      If i = 8 And Mid(role, i, 1) = "1" Then roles = roles & "Viewer, "
      If i = 10 And Mid(role, i, 1) = "1" Then roles = roles & "DEV, "
      If i = 11 And Mid(role, i, 1) = "1" Then roles = roles & "TL, "
      If i = 13 And Mid(role, i, 1) = "1" Then roles = roles & "TA, "
   Next

   MsgBox Left(roles, Len(roles) - 2)
End Sub
4 голосов
/ 21 февраля 2020

Может быть, вот отправная точка:

Sub Test()

Dim Dict As Object: Set Dict = CreateObject("Scripting.Dictionary")
Dim str As String, Role As String
Dim arr1 As Variant, arr2 As Variant

arr1 = Array(1, 7, 8, 10, 11, 13)
arr2 = Array("Admin", "TE", "Viewer", "DEV", "TL", "TA")

str = "100000010000100000"

For x = 0 To 5
    If Mid(str, arr1(x), 1) = 1 Then Dict(arr2(x)) = 1
Next

Role = Join(Dict.Keys, ", ")

End Sub

Не забудьте включить dict.RemoveAll, если вы собираетесь использовать это в итерации.


И для развлечения Evaluate опция:

Sub Test()

Dim str As String, Role As String
Dim arr1 As Variant, arr2 As Variant

str = "100000010000100000"

arr1 = Array("Admin", "TE", "Viewer", "DEV", "TL", "TA")
arr2 = Evaluate("IF(MID(""" & str & """,{1,7,8,10,11,13},1)=""1"",1,0)")

With Application
    Role = Join(Filter(.IfError(.Match(arr2, Array(0), 0), arr1), 1, False), ", ")
End With

End Sub
2 голосов
/ 22 февраля 2020

Есть ли необходимость сделать это в VBA?

Вот (глупый?) Способ сделать это просто на листе:

Начните с значений в столбце A. Через столбцы, поместите ваши значения для отдельных ролей ..

Вот как я настроил это на своем конце (вы всегда можете скрыть строки / столбцы, которые вам не нужны)

enter image description here

Формулы в каждой ячейке следующие:

D4: (скопировано в D6)

=SUMPRODUCT(--MID(A4,LEN(A4)+1-ROW(INDIRECT("1:"&LEN(A4))),1),(2^(ROW(INDIRECT("1:"&LEN(A4)))-1)))

E2: (скопировано в J2)

=SUMPRODUCT(--MID(E1,LEN(E1)+1-ROW(INDIRECT("1:"&LEN(E1))),1),(2^(ROW(INDIRECT("1:"&LEN(E1)))-1)))

E4: (скопировано до J6).

=BITAND($D4,E$2)

Очевидно, что вы можете объединить их, чтобы устранить лишние шаги (я оставил их для ясности).

Фанки:

=SUMPRODUCT(--MID(A4,LEN(A4)+1-ROW(INDIRECT("1:"&LEN(A4))),1),(2^(ROW(INDIRECT("1:"&LEN(A4)))-1)))

это просто хитрый способ сделать: BIN2DE C () на большее значение .. согласно эта нить:

bin2de c для чисел длиннее 10 бит в excel

после того, как они у вас есть в десятичной форме, их можно протолкнуть через BITAND :)

2 голосов
/ 21 февраля 2020

a) Подход через байтовый массив

В дополнение к приведенным выше действующим решениям и ради уровня техники существует другой подход с использованием байтового массива:

Sub ExampleCall()
    Dim s As String: s = "100000010000100000"
    Debug.Print s & " ~> " & getRole(s)          ' ~> Admin, Viewer, TA
End Sub

Функция справки getRole()

Function getRole(code As String) As String
'[0]define identifying role position in code string (e.g. "100000010000100000")
    Dim roles As Variant, b() As Byte
    roles = Array(0, "Admin", 2, 3, 4, 5, 6, "TE", "Viewer", 9, "DEV", "TL", 12, "TA", 14, 15, 16, 17, 18)
'[1]assign code string to byte array (generates two elements per character)
    b = code
'[2]get the "1" positions
    Dim i As Long, role As String
    For i = LBound(b) To UBound(b) - 1 Step 2   ' check the 1st element of each char pair
        If b(i) = Asc("1") Then role = role & roles(Int(i / 2) + 1) & ", "
    Next
    role = Left(role, Len(role) - 2)
'[3]return function result
    getRole = role
End Function
 ~~~~~~~~~~~~~~~~~~~~ Edit ~~~~~~~~~~~~~~~~~~~

b) Альтернатива через FilterXML() (Excel версии 13 +)

In Чтобы завершить весь спектр различных подходов, я продемонстрирую, как использовать функцию Worksheet FilterXML() (доступна в версиях 13+). Поскольку нет необходимости связываться с библиотекой, вы можете найти этот простой пример в качестве альтернативы словарям.

Sub ExampleCall2()
    Dim code As String: code = "100000010000100000"
    Debug.Print decode(code)
End Sub

Функции справки decode() и XMLRole()

Function decode(code) As String
    Dim pos As Long, cnt As Long, isReady As Boolean
    ReDim tmp(1 To Len(code))
    Do While Not isReady
        pos = InStr(pos + 1, code, "1")
        If pos = 0 Then
            isReady = True
        Else
            cnt = cnt + 1: tmp(cnt) = XMLRole(pos)
        End If
    Loop
    ReDim Preserve tmp(1 To cnt)
    decode = Join(tmp, ", ")
End Function

Function XMLRole(code) As String
    Const wellformed As String = "<roles><r t='Admin'>1</r><r t='TE'>7</r><r t='Viewer'>8</r><r t='DEV'>10</r><r t='TL'>11</r><r t='TA'>13</r></roles>"
    XMLRole = WorksheetFunction.FilterXML(wellformed, "//r[.=" & code & "]/@t")
End Function

Краткие подсказки для XPath

XPath Строки (здесь: "//r[.=" & code & "]/@t") позволяют искать содержимое узла или атрибута, обогащенное условиями (здесь, например: [.=11], указывающее на числовое c содержимое, например, 11) в хорошо сформированной структуре узла (сравнимой с html). Дополнительные подузлы или атрибуты добавляются / ко всему термину (здесь: содержание атрибута /@t (символизирующее тип , например, 'TL') после узла роли r; между прочим //r обозначает роль поиск любого r в любом месте после элемента root (здесь: roles).

0 голосов
/ 27 февраля 2020

спасибо всем за вашу помощь, мой окончательный код выглядит следующим образом:

Dim Role As String
Dim roles As String
Dim i As Integer
Dim c As Range
Dim b As Integer
b = 1
    For Each c In Range("A1", Range("A1").End(xlDown)).Rows
        Role = c.Value
        For i = 1 To Len(Role)
            If i = 1 And Mid(Role, i, 1) = "1" Then roles = roles & "Admin, "
            If i = 7 And Mid(Role, i, 1) = "1" Then roles = roles & "TE, "
            If i = 8 And Mid(Role, i, 1) = "1" Then roles = roles & "Viewer, "
            If i = 10 And Mid(Role, i, 1) = "1" Then roles = roles & "DEV, "
            If i = 11 And Mid(Role, i, 1) = "1" Then roles = roles & "TL, "
            If i = 13 And Mid(Role, i, 1) = "1" Then roles = roles & "TA, "
        Next
        Range("B" & b) = Left(roles, Len(roles) - 2)
        roles = ""
        b = b + 1
    Next c

У меня была небольшая проблема с циклическим переходом по каждой ячейке, но это только из-за моего небольшого знания AVB. Это не самый красивый код, но он служит своей цели, еще раз спасибо за помощь:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...