Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Microsoft Office и VBA программирование > Microsoft Office Excel
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.05.2009, 22:30   #11
Propan
Пользователь
 
Регистрация: 23.04.2009
Сообщений: 10
По умолчанию

Скайпа к сожалению нет. В коде массив d_mapping заполняется 3мя значениями. В d_mapping().sname вручную вносятся имена полей по которым ведётся поиск. Через два цикла заполняются d_mapping().scol1 - номер искомого столбца на 1ом листе, d_mapping().scol2 - номер искомого столбца на 2ом листе.
Propan вне форума Ответить с цитированием
Старый 03.05.2009, 23:00   #12
EducatedFool
Программист VBA
СуперМодератор
 
Аватар для EducatedFool
 
Регистрация: 13.07.2008
Сообщений: 6,858
По умолчанию

Вот теперь всё работает:
(только не забудьте на второй лист добавить столбец СУММА)

Код:
Option Compare Text
Type t_mapping: sname As String: scol1 As Integer: scol2 As Integer: End Type

Sub НоваяВерсия()
    Application.ScreenUpdating = False
    Dim d_mapping(1 To 4) As t_mapping
    Dim sh1 As Worksheet: Set sh1 = Sheets("Лист1")
    Dim sh2 As Worksheet: Set sh2 = Sheets("Лист2")
    sh1.UsedRange.EntireRow.Font.Bold = False: sh2.UsedRange.EntireRow.Font.Bold = False

    d_mapping(1).sname = "Фамилия": d_mapping(2).sname = "Имя"
    d_mapping(3).sname = "Отчество": d_mapping(4).sname = "Сумма"

    On Error Resume Next
    For i = LBound(d_mapping) To UBound(d_mapping)
        d_mapping(i).scol1 = sh1.Rows(1).Find(d_mapping(i).sname).Column
        d_mapping(i).scol2 = sh2.Rows(1).Find(d_mapping(i).sname).Column
        If d_mapping(i).scol1 = 0 Then MsgBox "На листе  Лист1  не найден столбец  " & _
           d_mapping(i).sname, vbCritical, "Ошибка": Exit Sub
        If d_mapping(i).scol2 = 0 Then MsgBox "На листе  Лист2  не найден столбец  " & _
           d_mapping(i).sname, vbCritical, "Ошибка": Exit Sub
    Next i

    arr1 = sh1.UsedRange.Offset(1).Value: arr2 = sh2.UsedRange.Offset(1).Value
    Dim coll As New Collection, collTemp As New Collection
    ' coll - коллекция значений повторяющихся строк, collTemp - уникальных

    For i = LBound(arr1) To UBound(arr1)
        v = Trim$(arr1(i, d_mapping(1).scol1)) & "#" & Trim$(arr1(i, d_mapping(2).scol1)) & _
            "#" & Trim$(arr1(i, d_mapping(3).scol1)) & "#" & Trim$(arr1(i, d_mapping(4).scol1))
        If Len(v) > UBound(d_mapping) - LBound(d_mapping) Then    ' если строка не пустая
            ' Debug.Print v
            Err.Clear: collTemp.Add v, v: If Err.Number = 457 Then coll.Add v, v
        End If
    Next i

    For i = LBound(arr2) To UBound(arr2)
        v = Trim$(arr2(i, d_mapping(1).scol2)) & "#" & Trim$(arr2(i, d_mapping(2).scol2)) & _
            "#" & Trim$(arr2(i, d_mapping(3).scol2)) & "#" & Trim$(arr2(i, d_mapping(4).scol2))
        If Len(v) > UBound(d_mapping) - LBound(d_mapping) Then    ' если строка не пустая
            ' Debug.Print v
            Err.Clear: collTemp.Add v, v: If Err.Number = 457 Then coll.Add v, v
        End If
    Next i
    Debug.Print "Уникальных записей: " & collTemp.Count & ",  повторяющихся: " & coll.Count

    ' а теперь перебираем всё по-новой :)
    For i = LBound(arr1) To UBound(arr1)
        v = Trim$(arr1(i, d_mapping(1).scol1)) & "#" & Trim$(arr1(i, d_mapping(2).scol1)) & _
            "#" & Trim$(arr1(i, d_mapping(3).scol1)) & "#" & Trim$(arr1(i, d_mapping(4).scol1))
        If Len(v) > UBound(d_mapping) - LBound(d_mapping) Then    ' если строка не пустая
            Err.Clear: coll.Add v, v
            sh1.Rows(i + 1).Font.Bold = Err.Number = 457
        End If
    Next i

    For i = LBound(arr2) To UBound(arr2)
        v = Trim$(arr2(i, d_mapping(1).scol2)) & "#" & Trim$(arr2(i, d_mapping(2).scol2)) & _
            "#" & Trim$(arr2(i, d_mapping(3).scol2)) & "#" & Trim$(arr2(i, d_mapping(4).scol2))
        If Len(v) > UBound(d_mapping) - LBound(d_mapping) Then    ' если строка не пустая
            Err.Clear: coll.Add v, v
            sh2.Rows(i + 1).Font.Bold = Err.Number = 457
        End If
    Next i
End Sub
Пример во вложении:
Вложения
Тип файла: rar 2.rar (14.1 Кб, 10 просмотров)
EducatedFool вне форума Ответить с цитированием
Старый 03.05.2009, 23:45   #13
Propan
Пользователь
 
Регистрация: 23.04.2009
Сообщений: 10
По умолчанию

Спасибо большое, в таком коде нужно разбираться, но это наименьшая из проблем)
Только почему-то в загруженном вами примере выделяются всё равно не те строки, которые полностью совпадают по 4 столбцам: Фамилия, Имя, Отчество, Сумма
Propan вне форума Ответить с цитированием
Старый 03.05.2009, 23:52   #14
Propan
Пользователь
 
Регистрация: 23.04.2009
Сообщений: 10
По умолчанию

Всё понял. Это не понимание возникло из-за повторения одной из строк два раза на втором листе
Propan вне форума Ответить с цитированием
Старый 04.05.2009, 02:26   #15
Propan
Пользователь
 
Регистрация: 23.04.2009
Сообщений: 10
По умолчанию

И ещё два вопроса.
С чем связано то, что когда я задаю в массив d_mapping ещё одно значение d_mapping(5).sname="Количество", то есть сравниваю по пяти столбцам, сравнение идёт всё равно только по 4ём

И когда вместо выделения жирным шрифтом хочу задать выделение серым цветом sh1.Rows(i + 1).Font.ColorIndex = 15, закрашиваются все ячейки диапазона
Propan вне форума Ответить с цитированием
Старый 04.05.2009, 06:47   #16
EducatedFool
Программист VBA
СуперМодератор
 
Аватар для EducatedFool
 
Регистрация: 13.07.2008
Сообщений: 6,858
По умолчанию

Вот исправленный Вариант:

Код:
Option Compare Text
Type t_mapping: sname As String: scol1 As Integer: scol2 As Integer: End Type
Dim d_mapping() As t_mapping, arr1(), arr2(): Const Sep = "#"

Sub ПримерИспользования()
    НоваяВерсия2 "Лист1", "Лист2", "Фамилия", "Имя", "Отчество", "Сумма", "Количество"
End Sub


Sub НоваяВерсия2(ByVal Sh1Name As String, ByVal Sh2Name As String, ParamArray ColumnsNames() As Variant)

    Application.ScreenUpdating = False: Dim i As Long
    Dim sh1 As Worksheet, sh2 As Worksheet: Set sh1 = Sheets(Sh1Name): Set sh2 = Sheets(Sh2Name)

    УбратьФорматирование sh1.UsedRange.EntireRow
    УбратьФорматирование sh2.UsedRange.EntireRow

    ReDim d_mapping(LBound(ColumnsNames) To UBound(ColumnsNames)) As t_mapping
    For i = LBound(ColumnsNames) To UBound(ColumnsNames)
        d_mapping(i).sname = ColumnsNames(i)
        ' Debug.Print d_mapping(i).sname
    Next i

    On Error Resume Next
    For i = LBound(d_mapping) To UBound(d_mapping)
        d_mapping(i).scol1 = sh1.Rows(1).Find(d_mapping(i).sname).Column
        d_mapping(i).scol2 = sh2.Rows(1).Find(d_mapping(i).sname).Column
        If d_mapping(i).scol1 = 0 Then MsgBox "На листе  " & Sh1Name & "  не найден столбец  " & _
           d_mapping(i).sname, vbCritical, "Ошибка": Exit Sub
        If d_mapping(i).scol2 = 0 Then MsgBox "На листе  " & Sh2Name & "  не найден столбец  " & _
           d_mapping(i).sname, vbCritical, "Ошибка": Exit Sub
    Next i

    arr1 = sh1.UsedRange.Offset(1).Value: arr2 = sh2.UsedRange.Offset(1).Value
    Dim coll As New Collection, collTemp As New Collection
    ' coll - коллекция значений повторяющихся строк, collTemp - уникальных

    On Error Resume Next
    For i = LBound(arr1) To UBound(arr1)
        v = Строка1(i)
        If Len(v) > UBound(d_mapping) - LBound(d_mapping) Then    ' если строка не пустая
            Err.Clear: collTemp.Add v, v: If Err.Number = 457 Then coll.Add v, v
        End If
    Next i

    For i = LBound(arr2) To UBound(arr2)
        v = Строка2(i)
        If Len(v) > UBound(d_mapping) - LBound(d_mapping) Then    ' если строка не пустая
            Err.Clear: collTemp.Add v, v: If Err.Number = 457 Then coll.Add v, v
        End If
    Next i
    Debug.Print "Уникальных записей: " & collTemp.Count & ",  повторяющихся: " & coll.Count

    ' а теперь перебираем всё по-новой :)
    For i = LBound(arr1) To UBound(arr1)
        v = Строка1(i)
        If Len(v) > UBound(d_mapping) - LBound(d_mapping) Then    ' если строка не пустая
            Err.Clear: coll.Add v, v: If Err.Number = 457 Then ФорматироватьСтроку sh1.Rows(i + 1)
        End If
    Next i

    For i = LBound(arr2) To UBound(arr2)
        v = Строка2(i)
        If Len(v) > UBound(d_mapping) - LBound(d_mapping) Then    ' если строка не пустая
            Err.Clear: coll.Add v, v: If Err.Number = 457 Then ФорматироватьСтроку sh2.Rows(i + 1)
        End If
    Next i
End Sub

Sub ФорматироватьСтроку(ByRef ra As Range)
    With ra.Font: .Bold = True: .Size = 12: .Color = vbRed: End With
End Sub

Sub УбратьФорматирование(ByRef ra As Range)
    With ra.Font: .Bold = False: .Size = 10: .Color = vbBlack: End With
End Sub

Function Строка1(Позиция As Long) As String
    For i = LBound(d_mapping) To UBound(d_mapping)
        Строка1 = Строка1 & Sep & arr1(Позиция, d_mapping(i).scol1)
    Next i: Строка1 = Mid$(Строка1, 2)
End Function
Function Строка2(Позиция As Long) As String
    For i = LBound(d_mapping) To UBound(d_mapping)
        Строка2 = Строка2 & Sep & arr2(Позиция, d_mapping(i).scol2)
    Next i: Строка2 = Mid$(Строка2, 2)
End Function

Пример во вложении:
Вложения
Тип файла: rar 2.rar (16.7 Кб, 9 просмотров)
EducatedFool вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
форматирование строк и запись в файл drVit Общие вопросы C/C++ 1 24.04.2009 20:18
форматирование beygul Помощь студентам 13 07.02.2009 21:18
Матрица A состоит из 8 строк и 6 столбцов. вычесть из всех её строк, начиная со второй, первую строку Dimak24 Помощь студентам 1 19.12.2008 15:45
Условное форматирование ZORRO2005 Microsoft Office Excel 6 29.09.2008 16:46
Excel max 256 строк VS user надо 300 строк Exo Microsoft Office Excel 3 10.01.2008 17:14