2016-01-23 4 views
0

Я пытаюсь найти все значения в столбце W, содержащие двоеточие, удалить двоеточие из значения в этой ячейке и отметить XID в столбце A той же строки. Затем посмотрите, есть ли какие-либо экземпляры значения внутри строк в столбцах CT & CU в строках, которые имеют этот XID. Если какие-либо экземпляры в столбцах CT & CU удаляют упомянутый двоеточие.Найти и заменить цикл в excel vba

Вещь о столбцах CT & CU есть другие двоеточия в строках, поэтому конкретный двоеточие должно быть удалено.

Пример: Скажем, столбец W содержит «Меньше: чем минимум» и в той же строке XID в строке A будет «562670-6». Теперь, когда цикл отметил XID, который имеет появление двоеточия (в данном случае «Less: Than Minimum»), меньший цикл внутри большого цикла будет просматривать все ячейки в столбцах CT & CU, которые имеют один и тот же XID в столбце A найдите любые ячейки, которые CONTAIN «Less: Than Minimum» (который на фотографии будет ячейкой CT2, где он содержит «PROP: МЕНЬШЕ: МИНИМАЛЬНО: БУДЕТ ...») и удалите двоеточие (так что это закончится тем, что «ПРОП: МЕНЬШЕ МИНИМАЛЬНО: БУДЕТ ...»).

Поскольку в каждой ячейке есть несколько столбцов CT & CU. Моя идея - искать «: Меньше: чем минимум:», потому что в начале и конце этой строки всегда будет двоеточие.

Я пытался решить эту задачу и добрался до этой точки

Option Explicit 

Public Sub colonCheck() 
Dim rng As Range, aCell As Range, bCell As Range, uRng As Range, uCell As Range 
Dim endRange As Long 
Dim opName As String, opName2 As String 
Dim xid As String 

endRange = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row 

Set rng = ActiveSheet.Range("W1:W" & endRange) 

Set aCell = rng.Find(What:=":", LookIn:=xlValues, _ 
      LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 

If Not aCell Is Nothing Then 
    Set bCell = aCell 
    opName = ":" & aCell.Value & ":" 
    'Type mismatch on rng = Replace(rng, ":", "") 
    rng = Replace(rng, ":", "") 
    aCell = rng 
    'set corrected value (sans-colon) to opName2 
    opName2 = aCell.Value 

    xid = ActiveSheet.Range("A" & aCell.Row).Value 
    'Whatever we add here we need to repeat in the if statement after do 
    'We have the option name and the xid associated with it 
    'Now we have to do a find in the upcharges column to see if we find the opName 
    'Then we do an if statement and only execute if the the Column A XID value matches 
    'the current xid value we have now 
    Set uRng = ActiveSheet.Range("W2:W" & endRange) 

    Set uCell = uRng.Find(What:=opName, LookIn:=xlValues, _ 
      LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 
    If Not uCell Is Nothing And ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
      uRng = Replace(uRng, opName, opName2) 
      uCell = uRng 
    End If 
    'Above code was added 

    Do 
     Set aCell = rng.FindNext(After:=aCell) 

     If Not aCell Is Nothing Then 
      If aCell.Address = bCell.Address Then Exit Do 
      'Repeat above code in here so it loops 
      opName = ":" & aCell.Value & ":" 
      rng = Replace(rng, ":", "") 
      aCell = rng 
      'set corrected value (sans-colon) to opName2 
      opName2 = aCell.Value 

      xid = ActiveSheet.Range("A" & aCell.Row).Value 
      'Whatever we add here we need to repeat in the if statement after do 
      'We have the option name and the xid associated with it 
      'Now we have to do a find in the upcharges column to see if we find the opName 
      'Then we do an if statement and only execute if the the Column A XID value matches 
      'the current xid value we have now 
      Set uRng = ActiveSheet.Range("W2:W" & endRange) 
      Do 
       Set uCell = uRng.FindNext(After:=uCell) 
       If Not uCell Is Nothing Then 
        Set uCell = uRng.Find(What:=opName, LookIn:=xlValues, _ 
         LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
         MatchCase:=False, SearchFormat:=False) 
        If Not uCell Is Nothing And ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
         uRng = Replace(uRng, opName, opName2) 
         uCell = uRng 
        End If 
       Else 
        Exit Do 
       End If 
      Loop 
      'Above code was added 
     Else 
      Exit Do 
     End If 
    Loop 
End If 
End Sub 

Я получаю Тип несовпадение Ошибки в строке

rng = Replace(rng, ":", "") 

я наткнулся на ответ на this question, который сказал, что «Заменить работает только со строковыми переменными», поэтому я считаю, что это может быть проблемой?

Как я могу изменить приведенный выше код, чтобы выполнить то, что я ищу? Существует ли другой подход (который все еще выполняется через VBA). Here is a screenshot of the layout and values for a reference

Update/Revision

Хорошо, так что я прогрессировал немного, будучи в состоянии успешно найти и заменить первый экземпляр опции двоеточие «Меньше чем: Минимум» меняется на «Меньше Than Minimum "как в колонках W & CT. Проблема, с которой я сталкиваюсь сейчас, заключается в правильном функционировании циклов Do. Вот точка я пришел (я включил некоторые комментарии в коде, мы надеемся, поможет направлять тех, кто хочет попробовать и помощь)

Option Explicit 

Public Sub MarkDuplicates() 
Dim rng As Range, aCell As Range, bCell As Range, uRng As Range, uCell As Range, sCell As Range 
Dim endRange As Long 
Dim opName As String, opName2 As String 
Dim xid As String 

endRange = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row 

Set rng = ActiveSheet.Range("W1:W" & endRange) 

Set aCell = rng.Find(What:=":", LookIn:=xlValues, _ 
      LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 

If Not aCell Is Nothing Then 
    'bCell now holds the original cell that found 
    Set bCell = aCell 
    'Add colon to beginning and end of string to ensure we only find and replace the right portion over in upcharge column 
    opName = ":" & aCell.Value & ":" 
    'Correct the value in column W 
    aCell = Replace(ActiveSheet.Range("W" & aCell.Row).Value, ":", "") 
    'Set corrected value (sans-colon) to opName2 and add colon to beginning and end of string 
    opName2 = ":" & aCell.Value & ":" 
    'Note the XID of the current row so we can ensure we look for the right upcharge 
    xid = ActiveSheet.Range("A" & aCell.Row).Value 
    'We have the option name and the xid associated with it 
    'Now we have to do a find in the upcharges column to see if we find the opName 
    'Then we do an if statement and only execute if the the Column A XID value matches 
    'the current xid value we have now 
    Set uRng = ActiveSheet.Range("CT2:CU" & endRange) 
    'Set uCell to the first instance of opName 
    Set uCell = uRng.Find(What:=opName, LookIn:=xlValues, _ 
      LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 
    'If there is an instance of opName and uCell has the value check if the xid matches to ensure we're changing the right upcharge 
    If Not uCell Is Nothing And ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
     Set sCell = uCell 
     'If so then replace the string in the upcharge with the sans-colon version of the string 
     uCell = Replace(ActiveSheet.Range("CT" & uCell.Row).Value, opName, opName2) 
    End If 

    Do 
     '>>>The .FindNext here returns Empty<<< 
     Set aCell = rng.FindNext(After:=aCell) 
     If Not aCell Is Nothing Then 
      'if aCell and bCell match then we've cycled through all the instances of option names with colons so we exit the loop 
      If aCell.Address = bCell.Address Then Exit Do 
      'Add colon to beginning and end of string to ensure we only find and replace the right portion over in upcharge column 
      opName = ":" & aCell.Value & ":" 
      'Correct the value in column W (Option_Name) 
      aCell = Replace(ActiveSheet.Range("W" & aCell.Row).Value, ":", "") 
      'Set corrected value (sans-colon) to opName2 and add colon to beginning and end of string 
      opName2 = ":" & aCell.Value & ":" 
      'Note the XID of the current row so we can ensure we look for the right upcharge 
      xid = ActiveSheet.Range("A" & aCell.Row).Value 

      Do 

       Set uCell = uRng.FindNext(After:=uCell) 
       If Not uCell Is Nothing Then 
        'Check to make sure we haven't already cycled through all the upcharge instances 
        If uCell.Address = sCell.Address Then Exit Do 
        'Correct the value in column CT 
        uCell = Replace(ActiveSheet.Range("CT" & uCell.Row).Value, opName, opName2) 
       Else 
        Exit Do 
       End If 
      Loop 
     Else 
      Exit Do 
     End If 
    Loop 
End If 
End Sub 

Как я заметил в коде, я, кажется, получение связаны до в самом начале первого Do Loop на линии

Do 
     '>>>The .FindNext here returns Empty<<< 
     Set aCell = rng.FindNext(After:=aCell) 

в .FindNext(After:=aCell) возвращается назад по какой-то причине, даже если я место двоеточие в клетках с «Прямые поставки: - .....» & "МАГАЗИН: ДВИГАТЕЛЬНАЯ СВЯЗЬ: - ....."

Любая идея, почему или любая идея, как я могу это исправить?

+0

Я думаю, что вы хотите сделать проще, используя формулу, а не VBA. Это вариант? Если это так, вы можете просто использовать функцию replace, чтобы заменить двоеточия на «» – Kharoof

+0

К сожалению, это не вариант.Кроме того, просто используя функцию replace, чтобы удалить двоеточия так, как вы описали, удалите двоеточия, которые все еще должны оставаться в столбцах CT & CU. – CaffeinatedCoder

ответ

1

Вы должны перебрать все клетки, как это:

For i = 1 To endRange 
    If Not aCell Is Nothing Then 

     opName = ":" & aCell.Value & ":" 

     aCell = Replace(ActiveSheet.Range("W" & aCell.Row).Value, ":", "") 

     opName2 = ":" & aCell.Value & ":" 

     xid = ActiveSheet.Range("A" & aCell.Row).Value 
     Set uRng = ActiveSheet.Range("CT2:CU" & endRange) 
     Set uCell = uRng.Find(What:=opName, LookIn:=xlValues, _ 
       LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
       MatchCase:=False, SearchFormat:=False) 

     If Not uCell Is Nothing And ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
      Set sCell = uCell 

      uCell = Replace(ActiveSheet.Range("CT" & uCell.Row).Value, opName, opName2) 
     End If 
Next i 

я просто счетчик здесь, но вы можете использовать его в качестве индекса строки:

Cells(i, "W") 'Cells(RowIndex, ColumnIndex) works great for single cells 

Если вы хотите сделать больше в этом цикле, я бы также рекомендовал писать функции, которые вы можете вызвать с определенными параметрами.

Например (не хороший):

Function Renaming(Cell as Range) 
    Renaming = ":" Cell.Value ":" 
End Function 

Тогда вы могли бы вызвать функцию:

Call Renaming(aCell) 

Я считаю, что это поможет вам немного.

Также вам не нужно указывать диапазон aCell на bCell, так как это останется неизменным. Если вы хотите сохранить значение где-то вам нужно объявить bCell как строка, а затем выполните следующие действия:

bCell = aCell.Value 

В противном случае эта часть кода является довольно бесполезным, так как диапазон вашей ячейки не изменится до тех пор, вы закончили с кодом.

Я сам новичок в VBA, но если какой-либо из кодов работает для вас, не стесняйтесь использовать его. Если есть какие-либо предложения по улучшению кода, я бы с удовольствием прочитал комментарии :)

+1

Вы подняли очень хорошие моменты и немного разобрались, думая, поэтому я очень благодарен, что вы потратили время, чтобы поделиться! Вы помогли мне до конца завершить свой последний продукт, спасибо! – CaffeinatedCoder

+0

На самом деле, я очень рад, что он сработал, спасибо за ваши отзывы! :) Я работал только около 3 месяцев с vba, но на Mac это было так сложно, что мне пришлось делать google looooot. Так что теперь, если я смогу помочь, я постараюсь сделать это :) – Kathara

+0

Ваш вход определенно сделал :) Я, сам, работал с vba в течение последних нескольких лет и действительно оттачивал его в прошлом году или поэтому, я чувствую, что прошел долгий путь (через поиск в Google и задание множества вопросов, таких как вы сами). Я до такой степени, что мне обычно нужен какой-то фундамент для проблемы, и я могу создать вокруг этого. Следовательно, почему ваши отзывы помогли мне до конца! – CaffeinatedCoder

1

Ваше несоответствие типа, я думаю, потому что вы пытаетесь использовать замену (которая работает со строками) по диапазону. Вместо этого вам нужно будет прокручивать каждый элемент диапазона и выполнять замену.Так что-то вроде:

Dim i As Integer 
i=1 
While i <= endRange 
    Replace(ActiveSheet.Cells(i,23).Value, ":", "") 
    i=i+1 
Wend 
+0

. Проблема с этим я не могу пропустить и исправить все значения столбца W, которые необходимо исправлять сразу, так как если вы посмотрите ниже первой замены, есть еще два замещения, которые необходимо выполнить для каждого экземпляра. Если я не пропущу что-то очевидное. В теории, вы думаете, что ваша идея может быть применена таким образом, чтобы я мог разместить весь код, начиная с права перед первым оператором замены? Как вы думаете, вы могли бы мне помочь? – CaffeinatedCoder

+0

Я не уверен, что полностью понимаю, о чем вы спрашиваете. Конечно, вы можете делать больше вещей внутри этого цикла. Это в основном просто делает все ваши строки, поэтому, когда я поставил замену, вы можете добавить больше на другие строки, чтобы делать другие ячейки или что-то еще, что необходимо для этой строки одновременно. Просто ссылайтесь на другие столбцы, где у меня есть 23 (это W). – andrewf

+0

См. Мое обновление. – CaffeinatedCoder

1

С некоторыми проб и ошибок (и помощь от @ Kathara, указывая несколько свободных концов, чтобы очистить и предложить способ пойти о моей петле) Я, наконец, пришел к полностью работающему решению. Однако вместо того, чтобы перебирать столбец параметров и затем перебирать критерии дозачисления 1 и критерии дозагрузки 2 столбца каждый раз, когда я сталкиваюсь с именем параметра с двоеточием, я пошел с методом Find(), так как знаю, что каждый раз, когда я нахожу первое значение из верхней части столбца «Имя параметра» значение будет одним из первых, которое будет выглядеть сверху вниз от столбцов «вверх». Я также решил разделить uRng на два диапазона (uRng1 для критериев дозарядки 1 и uRng2 для критериев дозачисления 2) и проверить uRng2 сразу после каждого раза, когда я проверяю uRng1, гарантируя, что я заменю имя параметра в обоих столбцах. Я удалил переменные диапазона sCell bCell , потому что, как указывала Катхара, они не являются жизненно важными для Sub. На самом деле, там просто был пример, который я использовал для сборки моего Sub, так вот откуда они пришли (хороший глаз Kathara!). Я также понял с помощью @andrewf, что я не выполнял функцию Replace() правильно, поскольку я предоставлял диапазон внутри него, а не значение текущей ячейки этого диапазона. Наконец, прежде чем кто-нибудь скажет, что я должен сохранить код Option Compare Text в своем коде, я понял, что он не будет летать позже в моем общем проекте, так как это один из них, который будет объединен с примерно 10 другими, чтобы сделать мой конечный продукт. Таким образом, вместо этого я упал на функцию UCase(), которая соответствует счету именно для того, что мне нужно выполнить. Итак, без дальнейших церемоний ниже приведен код. Если кто-то в будущем может получить хоть какую-то информацию или сможет использовать любую лакомые кусочки из моей работы, чтобы помочь им, я буду счастлив, зная, что смогу помочь в любом случае.

Sub dupOpCheck() 
Dim rng As Range, aCell As Range, uRng1 As Range, uRng2 As Range, uCell As Range 
Dim endRange As Long 
Dim opName As String, opName2 As String 
Dim xid As String 

endRange = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row 

Set rng = ActiveSheet.Range("W1:W" & endRange) 

Set aCell = rng.Find(What:=":", LookIn:=xlValues, _ 
      LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 

If Not aCell Is Nothing Then 
    'Add colon to beginning and end of string to ensure we only find and replace the right 
    'portion over in upcharge column 
    opName = ":" & aCell.Value & ":" 
    'Correct the value in column W 
    aCell = Replace(ActiveSheet.Range("W" & aCell.Row).Value, ":", "") 
    'Set corrected value (sans-colon) to opName2 and add colon to beginning and 
    'end of string 
    opName2 = ":" & aCell.Value & ":" 
    'Note the XID of the current row so we can ensure we look for the right upcharge 
    xid = ActiveSheet.Range("A" & aCell.Row).Value 
    'We have the option name and the xid associated with it 
    'Now we have to do a find in the upcharges column to see if we find the opName 
    'Then we do an if statement and only execute if the the Column A XID value matches 
    'the current xid value we have now 
    Set uRng1 = ActiveSheet.Range("CT1:CT" & endRange) 
    Set uRng2 = ActiveSheet.Range("CU1:CU" & endRange) 
    'Convert uRng1 & uRng2 to all uppercase just to make sure they will be detected when using Find 

    'Set uCell to the first instance of opName 
    Set uCell = uRng1.Find(What:=UCase(opName), LookIn:=xlValues, _ 
      LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 
    'If there is an instance of opName and uCell has the value check if the xid matches 
    'to ensure we 're changing the right upcharge 
    If Not uCell Is Nothing Then 
     If ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
      'If so then replace the string in the upcharge with the sans-colon version of the string 
      uCell = Replace(UCase(ActiveSheet.Range("CT" & uCell.Row).Value), UCase(opName), UCase(opName2)) 
     End If 
     'Now we look in upcharge_criteria_2 column 
     Set uCell = uRng2.Find(What:=UCase(opName), LookIn:=xlValues, _ 
      LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 
     If Not uCell Is Nothing Then 
      If ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
       'If so then replace the string in the upcharge with the sans-colon version of the string 
       uCell = Replace(UCase(ActiveSheet.Range("CU" & uCell.Row).Value), UCase(opName), UCase(opName2)) 
      End If 
     End If 
    Else 
     'Now we just look in upcharge_criteria_2 column since we didn't find an instance in upcharge_criteria_1 column 
     Set uCell = uRng2.Find(What:=UCase(opName), LookIn:=xlValues, _ 
      LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 
     If Not uCell Is Nothing Then 
      If ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
       'If so then replace the string in the upcharge with the sans-colon version of the string 
       uCell = Replace(UCase(ActiveSheet.Range("CU" & uCell.Row).Value), UCase(opName), UCase(opName2)) 
      End If 
     End If 
    End If 

    Do 
     'Check for Options 
     'Instead of After:=aCell we have to make a start of before aCell or maybe just start back at row 1? 
     'What:=":", After:=aCell 
     Set aCell = rng.Find(What:=":", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 
     If Not aCell Is Nothing Then 
      'Add colon to beginning and end of string to ensure we only find and 
      'replace the right portion over in upcharge column 
      opName = ":" & aCell.Value & ":" 
      'Correct the value in column W (Option_Name) 
      aCell = Replace(ActiveSheet.Range("W" & aCell.Row).Value, ":", "") 
      'Set corrected value (sans-colon) to opName2 and add colon to 
      'beginning and end of string 
      opName2 = ":" & aCell.Value & ":" 
      'Note the XID of the current row so we can ensure we look for the right upcharge 
      xid = ActiveSheet.Range("A" & aCell.Row).Value 
      Do 
       On Error GoTo D1 
       'Check the upcharges 
       Set uCell = uRng1.Find(What:=UCase(opName), LookIn:=xlValues, _ 
         LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
         MatchCase:=False, SearchFormat:=False) 
       If Not uCell Is Nothing Then 
        'Check to make sure we haven't already cycled through all 
        'the upcharge instances 
        If ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
         'Correct the value in column CT 
         uCell = Replace(UCase(ActiveSheet.Range("CT" & uCell.Row).Value), UCase(opName), UCase(opName2)) 
        End If 
        'Now we look in upcharge_criteria_2 column 
        Set uCell = uRng2.Find(What:=UCase(opName), LookIn:=xlValues, _ 
         LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
         MatchCase:=False, SearchFormat:=False) 
        If Not uCell Is Nothing Then 
         If ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
          'If so then replace the string in the upcharge with the sans-colon version of the string 
          uCell = Replace(UCase(ActiveSheet.Range("CU" & uCell.Row).Value), UCase(opName), UCase(opName2)) 
         End If 
        End If 
       Else 
        Set uCell = uRng2.Find(What:=UCase(opName), LookIn:=xlValues, _ 
         LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
         MatchCase:=False, SearchFormat:=False) 
        If Not uCell Is Nothing Then 
        'Check to make sure we haven't already cycled through all 
        'the upcharge instances 
         If ActiveSheet.Range("A" & uCell.Row).Value = xid Then 
          'Correct the value in column CT 
          uCell = Replace(UCase(ActiveSheet.Range("CU" & uCell.Row).Value), UCase(opName), UCase(opName2)) 
         End If 
        Else 
D1: 
         Exit Do 
        End If 
       End If 
      Loop 
     Else 
      Exit Do 
     End If 
    Loop 
End If 
End Sub 
+0

Я бы сказал, хорошо сделано, и я был рад помочь :) – Kathara

Смежные вопросы