Short question regarding excel formatting.
I am currently working on a userform-based protocol tool. The userform basically consists of two input windows, one which loads the exisitng bullet points and one to add new points.
Additionally, I would like to have the date in bold font added to each bullet point. I implemented that by searching for the position in the string where the date occurs (via instrrev) and then changing the font for the next 10 characters to bold font.
Now it works perfectly fine when creating a new bullet point, but it always messes up when I add an additional point to an existing topic or when I change an old bullet point (Then the whole text is bold). Anyone knows why this happens?
Private Sub Fertig_Click()
Dim neu As String
Dim i As Integer
neu = Date & ": " & mitschrieb_neu.Value
'No Changes
If mitschrieb_neu.Value = "" And mitschrieb_alt.Value = ActiveCell.Value Then
Unload Me
Exit Sub
End If
'First bullet point
If mitschrieb_neu.Value <> "" And ActiveCell.Value = "" Then
ActiveCell.Value = neu
i = InStrRev(ActiveCell.Value, Date)
ActiveCell.Characters(i, 10).Font.Bold = True
Unload Me
Exit Sub
End If
'New bullet point
If mitschrieb_neu.Value <> "" And ActiveCell.Value <> "" Then
ActiveCell.Value = ActiveCell.Value & Chr(10) & neu
i = InStrRev(ActiveCell.Value, Date)
ActiveCell.Characters(i, 10).Font.Bold = True
Unload Me
Exit Sub
End If
'Changed an old bullet point
If mitschrieb_neu.Value = "" And mitschrieb_alt.Value <> ActiveCell.Value Then
ActiveCell.Value = mitschrieb_alt.Value
Unload Me
Exit Sub
End If
End Sub
Once you execute this:
ActiveCell.Value = ActiveCell.Value & Chr(10) & neu
The Bold setting for the cell becomes uniform -- it erases any knowledge of substring formatting.
So the solution is to parse the complete value in a loop, and identify all the dates and make them bold.
At the same time I would suggest some way to reduce the duplication of code and merge all different cases (first bullet, not first bullet, modification only) into one generic way:
Private Sub Fertig_Click()
Dim neu As String
Dim i As Integer
'No Changes
If mitschrieb_neu.Value = "" And mitschrieb_alt.Value = ActiveCell.Value Then
Unload Me
Exit Sub
End If
' Join the old value with the new value and put a linefeed
' in between only if both are not empty.
' Also insert the date before the new value, if it is not empty
ActiveCell.Value = mitschrieb_alt.Value _
& IIf(mitschrieb_alt.Value <> "" And mitschrieb_neu.Value <> "", Chr(10), "") _
& IIf(mitschrieb_neu.Value <> "", Date & ": " & mitschrieb_neu.Value, "")
ActiveCell.Font.Bold = False ' start with removing all bold
' Search for all colons and put prededing date in bold (if it is a date)
i = InStr(ActiveCell.Value, ": ")
Do While i
' Make sure to only put in bold when it is a date, otherwise skip this ":"
If i > 10 And IsDate(Mid(ActiveCell.Value, i - 10, 10)) Then
ActiveCell.Characters(i - 10, 10).Font.Bold = True
End If
' find next
i = InStr(i + 1, ActiveCell.Value, ": ")
Loop
Unload Me
End Sub
Related
I'm developing in VBA Excel and I discovered that I use WorksheetFunction.Trim(Cells(1,1)) where this cells contain any colored element, this element become colored by default.
Here is my code:
Cells(4, 2) = Application.WorksheetFunction.Trim(UCase(Cells(4, 2)))
Did you see this issue before ?
How can I remove blank in the text without this issue ?
Thanks for your help !
For cells with mixed formatting, replacing the cell value will lose the mixed format: instead you need to work with the cell's Characters collection:
Sub tester()
Dim c As Range
For Each c In Range("B3:B10").Cells
TrimAndUppercase c
Next c
End Sub
Sub TrimAndUppercase(c As Range)
Dim i, prevSpace As Boolean
If Len(c.Value) > 0 Then
'trim the ends of the text
Do While Left(c.Value, 1) = " "
c.Characters(1, 1).Text = ""
Loop
Do While Right(c.Value, 1) = " "
c.Characters(Len(c.Value), 1).Text = ""
Loop
'reduce runs of multiple spaces to a single space
For i = c.Characters.Count To 1 Step -1
With c.Characters(i, 1)
If .Text = " " Then
'was the previous character a space?
If prevSpace Then
.Text = "" 'remove this space
Else
prevSpace = True
End If
Else
.Text = UCase(.Text)
prevSpace = False
End If
End With
Next i
End If
End Sub
Note there are some limits to the length of the text using this method, and it can be a little slow with large ranges.
finally, I used this instruction.
Cells(4, 2) = Replace(UCase(Cells(4, 2)), " ", "")
In fact, my cell contain parameters and we perfers to avoid to have blank between them for visibility.
Please could you help me a little bit? I am a complete beginner, I don't know anything about programming.
I have the following code that changes double spaces into single spaces and deletes "..." if it's at the beginning of the selected cell(s).
Sub Test()
Dim X As Long, Cell As Range
For Each Cell In Selection
For X = Len(Cell.Text) To 1 Step -1
If Cell.Characters(X - 1, 2).Text = " " Then Cell.Characters(X, 1).Text = ""
If Cell.Characters(1, 3).Text = "..." Then Cell.Characters(1, 3).Text = ""
Next
Next
End Sub
Please could you tell me how I could change the part If Cell.Characters(1, 3).Text so that it removes "..." if it's at the end of the selected cell(s)?
This is not that easy as may seem, since Excel has the inclination to adjust three dots into an ellipsis, making it a single character that's unrecognizable when compared to a dot (or three). Furthermore, you don't need to loop characters 1 by 1, instead you could use Like to check if a cell is ending with the three dots, or rather the ellipsis. Next to that, we can trim excessive space characters in a Range in one go, using Application.Trim() as shown here.
So let's look at example data like:
Then if we select this Range and go over its cells using, for example:
Sub Test()
Dim cl As Range
For Each cl In Selection
If cl.Value Like "*..." Then
cl.Value = Left(cl.Value, Len(cl.Value) - 3)
ElseIf cl.Value Like "*" & ChrW(8230) Then
cl.Value = Left(cl.Value, Len(cl.Value) - 1)
End If
Next
Selection.Value = Application.Trim(Selection)
End Sub
The results would then be:
And for the sake of fun alternatives, a RegEx approach:
Sub Test2()
Dim cl As Range
With CreateObject("vbscript.regexp")
.Global = True
.Pattern = "…$|\.{3}$"
For Each cl In Selection
cl.Value = .Replace(cl.Value, "")
Next
End With
Selection.Value = Application.Trim(Selection)
End Sub
Maybe this can help you: Use the replace methode to change two spaces into one space. To search for three points at the beginning use the left methode and if it's the case, cut it out with the right methode. Here you have to watch out. Excel often replace three point by the character 133. So you have additional to test for it.
Sub Test()
Dim cell As Range
For Each cell In Selection
cell.Value = Replace(cell.Value, " ", " ")
If Left(cell.Value, 3) = "..." Then
cell.Value = Right(cell.Value, Len(cell.Value) - 3)
End If
If Left(cell.Value, 1) = Chr(133) Then
cell.Value = Right(cell.Value, Len(cell.Value) - 1)
End If
Next
End Sub
I think you can use Characters(1,3).Insert("") to change the text
Sub Test()
Dim c As Range
Selection.Value = Application.Trim(Selection)
For Each c In Selection
If c.Characters(1,3).Text = "..." Then c.Characters(1,3).Insert("")
Next
End Sub
Hey I have been writing some code to add a part ID to a spreadsheet off of a user form in Excel VBA. I have been reading through different documentation and can not figure out why no matter what type of method of inserting a row I try it inserts a row with a repeating value instead of a blank one. If anyone knows how to specify blank, other than writing the whole row to blank and then writing my numbers I want after, that would be appreciated.
I have tried both the following lines to add a row
Cells (x+1 ,column).EntireRow.Insert Shift:= xlDown
ws1.Rows(x+1).Insert Shift:=xlDown
This is the function it is used in:
Public Sub Add(IDRange As Range)
SearchCell = Cells(x, IDRange.Column)
Cells(x, IDRange.Column).Select
Do
If SearchCell = PartID Then
MsgBox " this Company Already uses this part"
Exit Sub
ElseIf x <> StopRow Then
x = x + 1
SearchCell = Cells(x, IDRange.Column)
End If
Loop While x <> StopRow And SearchCell <> PartID
Cells(x + 1, IDRange.Column).EntireRow.Insert Shift:=xlDown
Cells(x, IDRange.Column).Value = PartID
MsgBox PartID & " has been added to Adress " & Cells(x, IDRange.Column).Address
Cells(x, IDRange.Column).Select
End Sub
Bellow is the function that calls the Add Function and where I belive it may be getting the company name from
Private Sub AddPart_Click()
AddPartCounter = 0
Company = UserForm1.CompanyBox.Value
PartID = UserForm1.PartBox.Value
If Company = "" Then
MsgBox " Please put in the company you would like the part to go under"
ElseIf PartID = "" Then
MsgBox " Please put in the Part you would like entered"
ElseIf UserForm1.Studs.Value = False And UserForm1.Spreaders.Value = False And UserForm1.Blocks.Value = False And UserForm1.Imma.Value = False Then
MsgBox "Please select the type of part you are trying to add"
Else
Dim CurrentCell
Set CurrentCell = Cells.Find(What:=Company, LookAt:=xlWhole)
If CurrentCell Is Nothing Then
MsgBox " Company Not Found "
Exit Sub
End If
x = CurrentCell.Row
Do
Set CurrentCell = CurrentCell.Offset(1, 0)
Loop While CurrentCell.Offset(1, 0) = "" And Not CurrentCell Is Nothing And CurrentCell.Offset(1, 0).Row <> thisvar.Row + 1
StopRow = CurrentCell.Row
'If they are trying to add a nut
If UserForm1.Imma.Value = True Then
Call Add(Nut_ID_Rng)
'IF they are trying to add a stud
ElseIf UserForm1.Studs.Value = True Then
Call Add(Stud_ID_Rng)
'If they are trying to add a block
ElseIf UserForm1.Blocks.Value = True Then
Call Add(Block_ID_Rng)
'If they are trying to add a spreader
ElseIf UserForm1.Spreaders.Value = True Then
Call Add(Spreader_ID_Rng)
End If
End If
AddPartCounter = 1
End Sub
I know that the repeating pattern is coming from the insert line through debugging but I can not figure out why I have tried changing variables to numbers and it still did the same thing. This what it looks like with the repeating values.
enter image description here
The problem is that you most likely have a value still stored in your clipboard when you execute the Macro. To fix that, simply add this line of dode before running the insert line:
Applcation.CutCopyMode = False
That will clear your clipboard and allow the inserted rows to be blank.
I have one column of data with either "UP", "DOWN" or "" as values. I am trying to write code that states that for all rows, if the first cell is "UP" then check the next rows until I come to either "DOWN" or "UP", i.e. if the next row has a "" then check the next row until I come to either a "DOWN" or "UP".
I am very new to VBA, and have tried various options, but seem to only be able to bring back where there are consecutive "UP"s or "DOWNS" rather than where there is an "UP", a number of rows of "" and then another "UP".
This is my code:
Range("z1:z250").Select
Selection.ClearContents
For Row = 2 To 250
If Range("Y" & Row).Value = "UP" Then
For sRow = 3 To 250
If Range("Y" & Row + 1).Value = "UP" Then
Range("Z" & Row) = "MT-UP"
ElseIf Range("Y" & Row + 1).Value = "" Then
End If
Next
End If
Next
End Sub
I have tried to add code such as For Each c in Range (“Y3”:”Y250”) but this doesn't make it find the next UP, and makes it very slow. I have also tried GoTo next cell (although seem to understand this is frowned upon!) but this doesn't work either. Any help appreciated.
Not 100% clear if this is what you want but take a look...
Instead of nested loops I used a flag to mark when a second consecutive "UP" was found before encountering a "DOWN". From your description it seems there's no need to check for empty cells ("").
Sub MTTest()
Dim Row As Long
Dim MTRow As Long
Dim MTFlag As Boolean
Range("Z1:Z250").ClearContents
For Row = 2 To 250
If Range("Y" & Row).Value = "UP" Then
If MTFlag = True Then
Range("Z" & MTRow) = "MT-UP"
MTFlag = Flase
Else
MTFlag = True
MTRow = Row
End If
Else
If Range("Y" & Row).Value = "DOWN" Then MTFlag = False
End If
Next
End Sub
Hi i am trying to create a macro that will loop through my worksheet and find a specific string of text. Once if has found that string i want it to look to the column next to it and if it says PoweredOn or PoweredOff then add 1 to a counter then display the number at the end.
in my excel i have column A as my virtual machines and in column B is the power state I have a loop setup to look for one virtual machine that is a template and is powered on but when i run my macro it prints it as 0 here is my code at the moment.
Dim POT As Integer
Dim POFFT As Integer
Sheets("tabvInfo").Select
Range("A2").Select
Do
If ActiveCell.Value = ("vCloud Cell Template") Then
If ActiveCell.Offset(0, 1).Value = ("PoweredOn") Then
POT = Selection.Cell.Count
Else
If ActiveCell.Offset(0, 1).Value = ("PoweredOff") Then
POFFT = Selection.Cell.Count
End If
End If
End If
ActiveCell.Offset(1, 0).Select
Loop Until IsEmpty(ActiveCell.Offset(1, 0))
MsgBox ("The number of powerered on VMs is " & POT)
MsgBox ("The number of powerered off VMs is " & POFFT)
Can anyone tell me why i am getting 0 as the result? I also need to make this look at other templates on my system while retaining the count of values would i need to create a do loop for each template or can i use an array to do this?
Try this instead
Sub Main()
Dim POT As Long
Dim POFFT As Long
Dim c As Range
For Each c In Sheets("tabvInfo").Range("A2:A" & Sheets("tabvInfo").Range("A" & Rows.Count).End(xlUp).Row)
If StrComp(c, "vCloud Cell Template", vbTextCompare) = 0 Then
If StrComp(c.Offset(0, 1), "PoweredOn", vbTextCompare) = 0 Then
POT = POT + 1
ElseIf StrComp(c.Offset(0, 1), "PoweredOff", vbTextCompare) = 0 Then
POFFT = POFFT + 1
End If
End If
Next
MsgBox ("The number of powerered on VMs is " & POT)
MsgBox ("The number of powerered off VMs is " & POFFT)
End Sub
It eliminates the .Select statement and .ActiveCell. It's a simple for loop that achieves what you want.
I am not sure you realize but you can achieve this using 2 very simple formulas for PoweredOn and Off
=COUNTIFS(A:A,"vCloud Cell Template",B:B, "PoweredOn")
=COUNTIFS(A:A,"vCloud Cell Template",B:B, "PoweredOFF")
Therefore to eliminate the need for using a loop you can
Sub NoLoop()
MsgBox "Powered ON: " & Evaluate("=COUNTIFS(A:A,""vCloud Cell Template"",B:B, ""PoweredOn"")")
MsgBox "Powered OFF: " & Evaluate("=COUNTIFS(A:A,""vCloud Cell Template"",B:B, ""PoweredOff"")")
End Sub