Обновить стиль Excel в VBA

#excel #vba

#excel #vba

Вопрос:

Мой макрос Excel считывает ответы на опрос из набора файлов Excel. Ответы опроса содержат оценку (от 1 до 4) и описание. Цель состоит в том, чтобы сгенерировать матрицу. Каждая ячейка матрицы имеет цвет, который представляет счет. Я хотел бы, чтобы пользователь мог изменять расположение этих ячеек. Чтобы упростить его для пользователя, я создал матрицу шаблонов и кнопку. Пользователь должен иметь возможность изменять расположение ячеек, и при нажатии кнопки должен быть создан набор стилей (оценка 1, оценка 2, …). После создания матрицы Рабочая книга должна функционировать без файлов опроса.

Я попробовал несколько вещей:

Попробуйте 1

 ThisWorkbook.Styles.Add "Score 1", BasedOn:=cell1
  

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

Попробуйте 2

 ThisWorkbook.Styles("Score 1").Delete
ThisWorkbook.Styles.Add "Score 1", BasedOn:=cell1
  

Это не очень хорошая идея: все ячейки теряют свой стиль при повторном выполнении.

Попробуйте 3: Текущий

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

Есть ли способ обновить стиль ячейки, который является более общим? Я бы хотел, чтобы было как можно меньше места для приведения рабочей книги в непоследовательное и нефункциональное состояние.

Ответ №1:

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

 'xR1_Template: the cell to base the style on
'nm_Style:    the name of the style
Public Function Upsert_Style(xR1_Template As Excel.Range, nm_Style As String) As Excel.Style
  
    Dim xStyle As Excel.Style
    Set xStyle = Fn.TryGet(ThisWorkbook.Styles, nm_Style)
    If Fn.IsNothing(xStyle) Then
        Set xStyle = ThisWorkbook.Styles.Add(nm_Style)
    End If

    xStyle.Font.Color = xR1_Template.Font.Color
    xStyle.Font.Bold = xR1_Template.Font.Bold
    xStyle.Font.Name = xR1_Template.Font.Name
    xStyle.Font.Italic = xR1_Template.Font.Italic
    xStyle.Font.Size = xR1_Template.Font.Size
    xStyle.Font.Strikethrough = xR1_Template.Font.Strikethrough
    xStyle.Font.Subscript = xR1_Template.Font.Subscript
    xStyle.Font.Superscript = xR1_Template.Font.Superscript

    xStyle.Font.Underline = xR1_Template.Font.Underline
    
    xStyle.Interior.Color = xR1_Template.Interior.Color
    xStyle.Interior.Pattern = xR1_Template.Interior.Pattern
    xStyle.Interior.PatternColor = xR1_Template.Interior.PatternColor

    'NOTE: necessary to delete all borders first. There's no way to delete them one by one.
    xStyle.Borders.LineStyle = xlNone
    
    Dim iBorder As Long
    For iBorder = 1 To xR1_Template.Borders.Count

       Dim xBorder As Excel.Border
       'NOTE:  The Borders property claims to work with xlBordersIndex argument, but this is not true.
    '       Normal indexing is used.
       Set xBorder = xR1_Template.Borders(iBorder)


       'NOTE:  "none-style" borders (=no border), should be skipped.
       '       Once they are retrieved using the Borders property, they are always visible.
       '       Setting them with xlLineStyle.xlLineStyleNone does not hide them.
       If xBorder.LineStyle <> XlLineStyle.xlLineStyleNone Then

            Dim xBorder_Style As Excel.Border
            Set xBorder_Style = xStyle.Borders(iBorder)

            xBorder_Style.Color = xBorder.Color
            xBorder_Style.LineStyle = xBorder.LineStyle
            xBorder_Style.Weight = xBorder.Weight
            
        End If

    Next iBorder
    
    xStyle.AddIndent = xR1_Template.AddIndent
    xStyle.FormulaHidden = xR1_Template.FormulaHidden
    xStyle.HorizontalAlignment = xR1_Template.HorizontalAlignment
    xStyle.IndentLevel = xR1_Template.IndentLevel
    xStyle.NumberFormat = xR1_Template.NumberFormat
    xStyle.NumberFormatLocal = xR1_Template.NumberFormatLocal
    xStyle.Orientation = xR1_Template.Orientation
    xStyle.ShrinkToFit = xR1_Template.ShrinkToFit
    xStyle.VerticalAlignment = xR1_Template.VerticalAlignment
    xStyle.WrapText = xR1_Template.WrapText
    xStyle.IndentLevel = xR1_Template.IndentLevel

    Set Upsert_Style = xStyle
    
End Function