Создание и управление коллекциями элементов управления времени выполнения по запросу

Это мой первый пост. Я пытался найти похожую тему, но не нашел.

Я новичок в VBA, и я учусь, пытаясь создать файл, который помогает спланировать вырезание частей из основной части.

Поскольку Excel VBA не позволяет рисовать фигуры или линии, я использую метки с рамкой для создания прямоугольников.

Прямоугольники обозначают разрезы, которые необходимо сделать.

Моя основная форма выглядит так:

Основная форма

Как вы можете видеть на изображении, в области, обозначенной красным прямоугольником, большой кусок размером 1600 мм (в этом примере) будет иметь семь разрезов по 60 мм.

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

Второй разрез

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

Код на данный момент слишком обширен, чтобы добавить его сюда, но мне удалось добавить некоторые функции, которые будут описаны ниже. Некоторые имена на португальском, но я не думаю, что это представляет проблему.

Здесь я создаю разрезы, определенные Ларгура: и Cortes reais:

Option Explicit
Public iCuts As Integer
Public Labels As Collection
Public newLabel As Object
Public bRecalculate As Boolean


Sub DrawCuts(NCuts As Integer, CutWidth As Double, TotalWidth)
Dim OriginX, OriginY As Integer
Dim labelCounter As Long
Dim labelCollection As New Collection


OriginX = 372
OriginY = 24
CutWidth = Multiplier(CutWidth, TotalWidth)

    For labelCounter = 0 To NCuts - 1
        Set newLabel = frmPlanning.Controls.Add("Forms.Label.1", "Corte" &     labelCounter, True)
        With newLabel
            .ControlTipText = .Name 'labelCounter + 1
            .Left = OriginX + CutWidth * labelCounter
            .Width = CutWidth
            .Height = 48
            .Top = OriginY
            .BackColor = &HFFFFFF
            .BorderStyle = 1
            .TextAlign = 2
            .Font.Size = 6
            .Caption = iCuts
        End With
        iCuts = iCuts + 1
    Next
    iCuts = iCuts - 1
End Sub

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

Sub Dim_Labels(Cuts As Integer, CutWidth As Double, RollWidth As Double,     RollLeft As Double)

    With frmPlanning.lCutWidth
        .Caption = CutWidth * Cuts
        .Width = Cuts * Multiplier(CutWidth, RollWidth)
    End With

    With frmPlanning.lCutLeft
        .Caption = RollLeft
        .Left = 372 + Cuts * Multiplier(CutWidth, RollWidth) 
        .Width = 320 - Cuts * Multiplier(CutWidth, RollWidth) 
    End With

    frmPlanning.lRollWidth = RollWidth
End Sub

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

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

Я не смог найти способ, но могу предоставить файл Excel, чтобы помочь вам лучше понять проблему, если есть способ.

Спасибо. Жулио

Правильно ли я резюмирую это, когда говорю, что вам нужны: A. X разрезает шириной w, где TotalCutsWidth (X * w) не превышает ширину большого блока (красный прямоугольник) (TotalWidth) B. Затем добавьте второй (третий, четвертый) массив таких разрезов (скажем: Y), который нужно складывать несколько раз. C. TotalCutsWidth для всех групп вместе взятых разрезов тоже не должно превышать TotalWidth? В итоге: пользователь может точно определить, сколько частей какой ширины он хочет из общего красного прямоугольника, и это должно быть нарисовано с помощью меток в этом верхнем правом поле?

Rik Sportel 04.09.2018 17:02

@RikSportel, спасибо за ответ. Да, но не уверен, что я правильно понял ваш пункт B, и, чтобы уточнить, второй, третий, ... разрезы могут иметь разную ширину, хотя все разрезы внутри партии будут иметь одинаковую ширину.

JJAA 04.09.2018 18:17

Да, это был пункт Б. Но после добавления всех «партий» они должны уместиться в большой коробке, правильно?

Rik Sportel 04.09.2018 18:39

Да, в конце концов, все они должны поместиться в большую коробку.

JJAA 05.09.2018 00:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, я думаю, это то, что вам нужно. Обратите внимание, что это не самый чистый код, но он выполняет отдельные части рисования в пользовательской форме.

Во-первых, я сохранил OriginX и OriginY в самой пользовательской форме - в конце концов, он должен контролировать, где должно начинаться рисование. Код пользовательской формы:

Public OriginX As Integer
Public OriginY As Integer
Private Sub UserForm_Initialize()
    OriginX = 20
    OriginY = 20
End Sub

Затем я создал класс BigBox для красного прямоугольника, который у вас был. У него есть высота, ширина, и при инициализации он добавит метку в пользовательскую форму. (Обратите внимание, что размещение метки в форме таким образом - плохая практика - класс не должен знать, где его нарисовать. Однако - для ответа на ваш вопрос это не актуально сразу.)

Класс BigBox:

Private p_width As Integer
Private p_height As Integer
Private p_label As MSForms.Label
Public Property Let Width(value As Integer)
    p_width = value
    p_label.Width = p_width
End Property
Public Property Get Width() As Integer
    Width = p_width
End Property
Public Property Let Height(value As Integer)
    p_height = value
    p_label.Height = p_height
End Property
Public Property Get Height() As Integer
    Height = p_height
End Property
Public Property Get Label() As MSForms.Label
    Set Label = p_label
End Property
Private Sub Class_Initialize() 'This bit is bad practice, but it works:
    Set p_label = frmPlanning.Controls.Add("Forms.Label.1", "BigBox", True)
    p_label.Left = frmPlanning.OriginX
    p_label.Top = frmPlanning.OriginY
    p_label.BorderColor = Red
    p_label.BorderStyle = 1
End Sub

Затем я создал класс «Cut», который можно использовать в коллекции с разрезами, поэтому, когда вам нужно перерисовать, вы сохраните их / они не будут забыты:

Класс резки:

Private p_width As Integer
Private p_height As Integer
Public Property Let Width(value As Integer)
    p_width = value
End Property
Public Property Get Width() As Integer
    Width = p_width
End Property
Public Property Let Height(value As Integer)
    p_height = value
End Property
Public Property Get Height() As Integer
    Height = p_height
End Property

Затем я изолировал коллекции «Cuts» и «Labels», так как метки нужно удалить и перерисовать, когда вы добавите второй пакет. Следующая процедура

  • Убедитесь, что коллекция Cuts и коллекции этикеток существуют.
  • Показывает форму (без режима, поэтому выполнение кода продолжается)
  • Создает BigBox и устанавливает высоту и ширину. Отсюда все разрезы будут иметь высоту.
  • Добавляет пару раз сокращений.
  • Имеет ли подпрограмма "добавить вырез" также для выполнения подпрограммы рисования.

Код модуля1:

Option Explicit
Public bb As BigBox
Public cuts As Collection
Public cutLabels As Collection
Public totalCutsWidth As Integer
Public piece As Cut
Sub test2()
    If cuts Is Nothing Then
        Set cuts = New Collection
    End If
    If cutLabels Is Nothing Then
        Set cutLabels = New Collection
    End If

    frmPlanning.Show vbModeless

    Set bb = New BigBox
    bb.Height = 100
    bb.Width = 500
    AddCuts 5, 20
    AddCuts 10, 10
    AddCuts 7, 50
End Sub

Sub AddCuts(numberOfCuts As Integer, widthOfCuts As Integer)
Dim i As Integer
If numberOfCuts <= 0 Then Exit Sub
For i = 1 To numberOfCuts
    Set piece = New Cut
    piece.Width = widthOfCuts
    piece.Height = bb.Height
    totalCutsWidth = totalCutsWidth + widthOfCuts
    If totalCutsWidth <= bb.Width Then
        cuts.Add piece
    End If
Next i
DrawCuts
End Sub
Sub DrawCuts()
Dim i As Integer
Dim OffsetX As Integer
Dim newLabel As MSForms.Label

OffsetX = 0

For i = cutLabels.Count To 1 Step -1
    frmPlanning.Controls.Remove "Corte" & i
    cutLabels.Remove i
Next i

i = 0
OffsetX = frmPlanning.OriginX
For Each piece In cuts
    i = i + 1
    Set newLabel = frmPlanning.Controls.Add("Forms.Label.1", "Corte" & i, True)
    With newLabel
        .ControlTipText = .Name
        .Left = OffsetX
        .Width = piece.Width
        .Height = piece.Height
        .Top = frmPlanning.OriginY
        .BackColor = &HFFFFFF
        .BorderStyle = 1
        .TextAlign = 2
        .Font.Size = 6
        .Caption = i
        OffsetX = OffsetX + piece.Width
    End With
    cutLabels.Add newLabel
Next piece
End Sub

Обратите внимание, что добавление разрезов гарантирует, что разрезы по-прежнему помещаются в большую рамку, и что рисунок разрезов отделен от него. Кроме того, если следующий кусок больше не помещается в коробке, он не будет добавлен. Т.е. если большая коробка имеет ширину 500, и вы добавляете 10 разрезов шириной 25, а затем 11 разрезов шириной 30, он добавит только первые 8 из второй партии (10 * 25 = 250, 8 * 30 = 240, 240 + 250 = 490, поэтому 9-й, 10-й и 11-й не помещаются в общую ширину 500, поэтому не будут добавлены.

Надеюсь, это поможет и достаточной информации для включения в существующее решение.

Привет, Рик. Вы молодцы только благодаря своей работе. Думаю, отсюда я справлюсь. Я попробую код и вернусь к вам, как только он будет работать над моим файлом (надеюсь). Спасибо.

JJAA 06.09.2018 09:54

Привет, @RikSportel, извиняюсь за поздний ответ. У меня не было времени на это смотреть (приоритеты постоянно меняются!) ... У меня нет слов, чтобы поблагодарить вас. Код прекрасно работает. Мне пришлось внести некоторые незначительные изменения, чтобы интегрировать его в существующий код, но он работал нормально. Благодаря этому я также узнал, как работают классы и коллекции, и теперь понимаю их намного лучше. У меня все еще есть некоторые проблемы, которые нужно решить, но это больше вопрос организации моего кода, чем чего-либо еще. Еще раз спасибо за вашу помощь. С уважением.

JJAA 11.09.2018 15:04

Другие вопросы по теме