I am coding a VBA function to merge two cells and then highlight the text of cell 2 with bold formatting
The merging goes well
The call to Sub goes well
But the text format is not applied
I believe it might be caused by the sub executing before the cell is populated with the string - but that's pure guessing - this is my first VBA script
Function boldIt(navn As String, ekstra As String)
Dim ln1 As Integer
Dim ln2 As Integer
Dim st1 As String
ln1 = Len(navn)
ln2 = Len(navn) + Len(ekstra)
If (ln1 = ln2) Then
boldIt = navn
Else
boldIt = navn & " - " & ekstra
boldTxt ln1, ln2
End If
End Function
Public Sub boldTxt(startPos As Integer, charCount As Integer)
With ActiveCell.Characters(Start:=startPos, Length:=charCount).Font
.FontStyle = "Bold"
End With
End Sub
I think I would just run two subs; the function is not returning anything.
Option Explicit
Sub boldIt()
Dim secondOne As String
With Selection
secondOne = .Cells(2).Value2
Application.DisplayAlerts = False
.Merge
Application.DisplayAlerts = True
.Cells(1) = .Cells(1).Value2 & secondOne
boldTxt .Cells(1), Len(.Cells(1).Value2) - Len(secondOne) + 1, Len(secondOne)
End With
End Sub
Public Sub boldTxt(rng As Range, startPos As Integer, charCount As Integer)
With rng.Characters(Start:=startPos, Length:=charCount).Font
.FontStyle = "Bold"
End With
End Sub
This Sub loops through the columns, takes the strings of the two cells, combines the strings and add them to the target cell, while bolding the text of the second cell
Thanks to #Jeeped for the pointers!
Sub boldIt()
Dim pos_bold As Integer
Dim celltxt As String
For i = 2 To 200000
' first cell will always be populated - if not - exit
If (Range("Plan!E" & i).Value = "") Then Exit For
' if second cell is empty - take only first cell as normal txt
If (Range("Plan!F" & i).Value = "") Then
Range("Kalender!F" & i).Value = Range("Plan!E" & i).Value
Else
' calculate start of bold text
pos_bold = Len(Range("Plan!E" & i).Value) + 1
' create the string
celltxt = Range("Plan!E" & i).Value & " - " & Range("Plan!F" & i).Value
' add string to field and add bold to last part
With Worksheets("Kalender").Range("F" & i)
.Value = celltxt
.Characters(pos_bold).Font.Bold = True
End With
End If
Next i
End Sub
Related
I get a mismatch error in this line :
row_str = Join(cell_rng, Chr(10))
Thank you. I am intermediate.
I attached a piece of the code below:
Dim last_row As String
Dim last_col As String
Dim office_str As String
Dim lookupVal As String
Dim i As Long
Dim seperate_cells, cell_rng As Range
Dim r As Range
Dim row_str As String
With Contacts
For i = 2 To last_row
Set cell_rng = Rows(i & ":" & i + 1)
For Each r In cell_rng.Rows
seperate_cells = cellsSeparator(r.SpecialCells(xlCellTypeConstants))
If row_str = "" Then
row_str = Join(cell_rng, Chr(10))
Else
row_str = row_str & vbLf & Join(cell_rng, Chr(10))
End If
Next
Debug.Print row_str
Client_Finder.result.Text = Client_Finder.result.Text & vbLf & row_str
Next i
End With
````
Please try the next way. It will place the values of the necessary specific row in the text box, each value separated by " | ":
Sub testSeparatorsBetweenRowCells()
'your existing code...
Dim arr, rngR As Range
For i = 2 To last_row
lookupVal = cells(i, office_str)
' Compare ComboBox with the range from the spreadsheet
If lookupVal = Office_Code Then
Set rngR = rows(i & ":" & i).SpecialCells(xlCellTypeConstants) 'Set a range which will return all cells value in the row, except the empty ones
arr = arrCells(rngR) 'call a function able to make an array from the range set in the above line
Client_Finder.result.Text = Client_Finder.result.Text & vbLf & Join(arr, " | ") 'add the text obtained by joining the array to the next line of existing text
End If
Next i
End Sub
Function arrCells(rng As Range) As Variant
Dim arr, Ar As Range, i As Long, C As Range
ReDim arr(rng.cells.count - 1) 'ReDim the array to be filled as the range cells number.
'- 1, because the array is 0 based...
For Each Ar In rng.Areas 'iterate between the range areas
For Each C In Ar.cells 'iterate between cells of each area
arr(i) = C.value: i = i + 1 'put each cell value in the array
Next
Next
arrCells = arr 'make the function returning the arr
End Function
If the text in the text box still goes on the next line, try making the text box property WordWrap False. If you cannot see all the text, make the textbox wider or decrease its font size.
Please, test it and send some feedback.
Edited:
Please, try understanding the next piece of code, able to deal with copying more rows at once:
Sub testCopyingMoreRows()
Dim sh As Worksheet, i As Long, rng As Range, r As Range, arr, strRow As String
Set sh = ActiveSheet
i = 9
Set rng = sh.rows(i & ":" & i + 1)
'you ca select cells, rows (even not consecutive) and use:
'Set rng = Selection.EntireRow 'just uncomment this code line...
'extract rows and paste their contents (exept the empty cells) in Imediate Window
For Each r In rng.rows
arr = arrCells(r.SpecialCells(xlCellTypeConstants))
If strRow = "" Then
strRow = Join(arr, " | ")
Else
strRow = strRow & vbLf & Join(arr, " | ")
End If
Next
Debug.Print strRow
'instead returning in Imediate Window, you can do it in your text box (uncomment the next line):
'Client_Finder.result.Text = Client_Finder.result.Text & vbLf & strRow
End Sub
The code uses the same function arrCells...
I have a code that can generate page number on cells.
But I want it apply to mutiple cells in one time instead of single cells.
Sub pagenumber()
'updateby Extendoffice 20160506
Dim xVPC As Integer
Dim xHPC As Integer
Dim xVPB As VPageBreak
Dim xHPB As HPageBreak
Dim xNumPage As Integer
xHPC = 1
xVPC = 1
If ActiveSheet.PageSetup.Order = xlDownThenOver Then
xHPC = ActiveSheet.HPageBreaks.Count + 1
Else
xVPC = ActiveSheet.VPageBreaks.Count + 1
End If
xNumPage = 1
For Each xVPB In ActiveSheet.VPageBreaks
If xVPB.Location.Column > ActiveCell.Column Then Exit For
xNumPage = xNumPage + xHPC
Next
For Each xHPB In ActiveSheet.HPageBreaks
If xHPB.Location.Row > ActiveCell.Row Then Exit For
xNumPage = xNumPage + xVPC
Next
ActiveCell = "Page " & xNumPage & " of " & Application.ExecuteExcel4Macro("GET.DOCUMENT(50)")
End Sub
What can i do for this? Is it also possible for apply the code to highlighted cells?
At the end write this:
Range("A1:B10")="Page "&xNumPage&" of "& Application.ExecuteExcel4Macro("GET.DOCUMENT(50)")
Instead of:
ActiveCell = "Page "&xNumPage& " of " & Application.ExecuteExcel4Macro("GET.DOCUMENT(50)")
Making sure that Range("A1:B10") is the range to which you want to apply the numbers.
How to avoid using Select in Excel VBA
I have been experimenting with adding tables in word from database.
So far I made a table in word document as a template
Then what I do is that I copy it into a new word document, search for DT and Dokumenttype and then replace it with the value I want. This is properly slow(however it seems to go extremly fast)and it would propberly be better to create it directly in word.
After creating the table i start adding rows to it, where the first column is to be hyperlinked. This is what seems to take time, it is only 235 rows total split on 11 tables but it takes almost a minute to create the 11 tables. So my question is how does you folks normally creates tables?
Do you create the header of the table, then keep adding rows?
Do you double loop, to find number of rows needed then create the whole table at one go?
Do you copy an array into the table to fill the rows? Then reloop to hyperlink the first column?
Output looks like this:
Below is my current code:
Option Explicit
Public Sub createDocOut(projectNumber As String, Optional reloadDatabase As Boolean = False)
Dim docOutArray() As String
Dim previousDokType As String
Dim doc_ As Document
Dim i As Long
Dim j As Integer
Dim k As Integer
Dim m As Integer
Dim sPercentage As Double
Dim numOfRows As Long
'Application.ScreenUpdating = False
docOutArray = Post.helpRequest("http://proto-ls/wordin.asp?Dok4=" & projectNumber)
If CPearson.IsArrayEmpty(docOutArray) Then
MsgBox "No document registered in database!"
End If
numOfRows = UBound(docOutArray, 1)
' creates a new document if needed otherwise it opens it
Set doc_ = NEwDocOut.createDocOutDocument(projectNumber)
If CustomProperties.getValueFromProperty(doc_, "_DocumentCount") = numOfRows And reloadDatabase = False Then
Application.ScreenUpdating = True
Exit Sub
Else
Selection.WholeStory
Selection.Delete
End If
'We add number of rows to document
Call CustomProperties.createCustomDocumentProperty(doc_, "_DocumentCount", numOfRows)
j = 0
previousDokType = ""
For i = LBound(docOutArray, 1) To numOfRows
'new table
If docOutArray(i, 1) <> previousDokType Then
If j > 0 Then
doc_.Tables(j).Select
Selection.Collapse WdCollapseDirection.wdCollapseEnd
Selection.MoveDown Unit:=wdLine, Count:=1
End If
j = j + 1
m = 2
Call NEwDocOut.addTable(doc_, docOutArray(i, 1), docOutArray(i, 2))
End If
'new row
With doc_.Tables(j)
.Rows(m).Select
Selection.InsertRowsBelow (1)
m = m + 1
' Hyper link the file
ActiveDocument.Hyperlinks.Add Anchor:=.Cell(m, 1).Range, _
Address:="z:\Prosjekt\" & projectNumber & docOutArray(i, 3), ScreenTip:="HyperLink To document", _
TextToDisplay:=FileHandling.GetFilenameFromPath(docOutArray(i, 3))
'loop through cells
For k = 3 To UBound(docOutArray, 2)
' .Cell(m, k - 2).Range.Font.Bold = False
' .Cell(m, k - 2).Range.Font.name = "Times New Roman"
' .Cell(m, k - 2).Range.Font.Size = 10
If k > 3 And k <> 8 Then
.Cell(m, k - 2).Range.Text = docOutArray(i, k)
End If
If k = 8 Then
.Cell(m, k - 2).Range.Text = Format(replace(docOutArray(i, k), ".", "/"), "mm.dd.yyyy")
End If
Next k
End With
previousDokType = docOutArray(i, 1)
Next i
'Application.ScreenUpdating = True
End Sub
'**********************************************************************
' ****** CREATE NEW DOCUMENT OUT **************************************
'**********************************************************************
Function createDocOutDocument(prosjektnumber As String) As Document
Dim dirName As String
Dim docOutname As String
Set createDocOutDocument = Nothing
' Hvis directory \Dokumentstyring\PFK ikke eksisterer, lag dette
dirName = "z:\Prosjekt\" & prosjektnumber
'change permision if needed
If Dir(dirName, vbDirectory) = "" And Not Settings.debugMy Then
MkDir dirName
End If
'filename of docOut
docOutname = dirName & "\" & prosjektnumber & "-Dokut.docx"
If FileHandling.doesFileExist(docOutname) Then
If FileHandling.openDocument(docOutname, True, True) Then
Set createDocOutDocument = ActiveDocument
Exit Function
End If
End If
'
' Add the tamplate for DocOut and save it to Doclist
'
Set createDocOutDocument = Documents.Add(Template:="Z:\Dokumentstyring\Config\DocOut.dotm", NewTemplate:=False)
createDocOutDocument.SaveAs filename:=docOutname
'Final check if document was created
If Not FileHandling.doesFileExist(docOutname) Then
Set createDocOutDocument = Nothing
End If
End Function
Function addTable(doc_ As Document, category As String, description As String)
doc_.Activate
'Insert out table
Selection.InsertFile filename:="Z:\Dokumentstyring\Config\Doklistut.docx", Range:="", _
ConfirmConversions:=False, link:=False, Attachment:=False
'Replace the DT with the category
If Not searchAll(doc_, "DT", category) Then
MsgBox "Failed to replace category in table"
End If
'Replace the Dokumenttype with the category
If Not searchAll(doc_, "Dokumenttype", description) Then
MsgBox "Failed to replace document type in table"
End If
End Function
I am trying to input multiple rows in a textbox and display each value in a different row of a single column in excel, My code inputs all values in different rows of the column. Code is as follows
Private Sub CommandButton1_Click()
Dim i As Variant
For Each i In Split(TextBox1.Text, vbCrLf)
With Range("A1")
lastrow = ThisWorkbook.Worksheets("sheet1").Range("A" & Rows.Count).End(xlUp).Row + 1
ThisWorkbook.Worksheets("sheet1").Range("A" & lastrow).Value = TextBox1.Value
End With
Next
TextBox1.Text = ""
End Sub
Any suggestions please? your response will be highly appreciated
if I understand it correctly you want to have each line in the text box in its own row so this would work
Private Sub CommandButton1_Click()
Dim i As Variant
Dim rowCounter As Long
rowCounter = 1
For Each i In Split(TextBox1.Text, vbCrLf)
'start at row 1 column A
Cells(rowCounter, 1).Value = i
rowCounter = rowCounter + 1
Next
TextBox1.Text = ""
End Sub
There is no need to iterate. Split returns an array that you can use to fill all the rows at once.
Private Sub CommandButton1_Click()
Dim Target As Range
Dim Data As Variant
If TextBox1.Text = "" Then Exit Sub
Data = Split(TextBox1.Text, vbCrLf)
With Worksheets("sheet1")
Set Target = .Range("A" & .Rows.Count).End(xlUp)
If Target.Value <> "" Then Set Target = Target.Offset(1)
Target.Resize(UBound(Data) + 1).Value = Application.Transpose(Data)
End With
TextBox1.Text = ""
End Sub
I'm trying to extract text content from Excel using a macro. This is my code:
Dim i As Integer, j As Integer
Dim v1 As Variant
Dim Txt As String
v1 = Range("A2:C15")
For i = 1 To UBound(v1)
For j = 1 To UBound(v1, 2)
Txt = Txt & v1(i, j)
Next j
Txt = Txt & vbCrLf
Next i
MsgBox Txt
But it is showing the raw characters only meaning that it doesn't show any formatting information like bold, italic, underline, etc..
I want to extract the text along with the formatting information.
Example: This is sample text
Expected output: This is sample text
Actual output: This is sample text
Can someone explain what's wrong with the code and tell if anything is wrong?
A messagebox does not permit formatiing without changing system defaults, which is not a starightforward approach. If you want to display formatted text in a prompt then you are probably easiest to create a userform and format the label appropriately.
For example, you can determine if a cell has bold fomatting using:
Dim isBold As Boolean
isBold = v1(i, j).Font.Bold
And apply this to a userform label font using:
label.Font.Bold = isBold
If you want to output to a text (ie .txt) file then this cannot store any formatting information. The best you could hope to achieve is to create a markup style output where:
If isBold Then
txt = "<b >mytext< /b>" 'Ignore the spaces
Else
txt = "mytext"
End If
The range.Font.Bold property has three return options:
v1(i, j).Font.Bold = True 'if the entire cell IS bold
v1(i, j).Font.Bold = False 'if the entire cell IS NOT bold
v1(i, j).Font.Bold = Null 'if the cell is PARTIALLY bold
Calling IsNull(v1(i, j).Font.Bold) will tell you whether you have partial fomatting in a cell. Unfortunately you must then assess each character in the string individually to determine the bold characters. This function should determine where the bold formatting is switched on or off in a string contained in the Range object passed and add the appropriate markup tag:
Function markup(rng As Range) As String
Dim chr As Integer
Dim isCharBold As Boolean
Dim str As String
Dim tempChar As Characters
isCharBold = False
str = ""
If IsNull(rng.Font.Bold) Then
For chr = 1 To rng.Characters.Count
Set tempChar = rng.Characters(chr, 1)
If isCharBold Then
If tempChar.Font.Bold Then
str = str + tempChar.Text
Else
isCharBold = False
str = str & "</b>" & tempChar.Text
End If
Else
If tempChar.Font.Bold Then
isCharBold = True
str = str + "<b>" & tempChar.Text
Else
str = str & tempChar.Text
End If
End If
Next chr
Else
str = rng.Value
End If
markup = str
End Function
Notice that the Else case just returns the default string values. You can modify this approach to work for any of the .Font properties e.g. strikethrough, underline, italic....
The framework in the OP suggests that you are assigning the contents of a range of cells into an array of type Variant. This essentially leaves you with an unformatted string of characters in each array index. In this case you won't be able to extract any formatting from the array strings. To access the Characters().Font.Bold property you must be operating on a Range object so it might be best to iterate through each cell in Range("A2:C15") directly. This could be achieved by modifying your initial code as such, so it now calls the markup function:
Sub OutputText()
Dim i As Integer, j As Integer
Dim rng As Range
Dim Txt As String
Set rng = Range("A2:C15")
For i = 1 To rng.Rows.Count
For j = 1 To rng.Columns.Count
Txt = Txt & markup(rng(i, j)) & " "
Next j
Txt = Txt & vbCrLf
Next i
Debug.Print Txt
End Sub
OK, let's have the algorithm from #stucharo a little bit simpler to extend.
Public Function getHTMLFormattedString(r As Range) As String
isBold = False
isItalic = False
isUnderlined = False
s = ""
cCount = 0
On Error Resume Next
cCount = r.Characters.Count
On Error GoTo 0
If cCount > 0 Then
For i = 1 To cCount
Set c = r.Characters(i, 1)
If isUnderlined And c.Font.Underline = xlUnderlineStyleNone Then
isUnderlined = False
s = s & "</u>"
End If
If isItalic And Not c.Font.Italic Then
isItalic = False
s = s & "</i>"
End If
If isBold And Not c.Font.Bold Then
isBold = False
s = s & "</b>"
End If
If c.Font.Bold And Not isBold Then
isBold = True
s = s + "<b>"
End If
If c.Font.Italic And Not isItalic Then
isItalic = True
s = s + "<i>"
End If
If Not (c.Font.Underline = xlUnderlineStyleNone) And Not isUnderlined Then
isUnderlined = True
s = s + "<u>"
End If
s = s & c.Text
If i = cCount Then
If isUnderlined Then s = s & "</u>"
If isItalic Then s = s & "</i>"
If isBold Then s = s & "</b>"
End If
Next i
Else
s = r.Text
If r.Font.Bold Then s = "<b>" & s & "</b>"
If r.Font.Italic Then s = "<i>" & s & "</i>"
If Not (r.Font.Underline = xlUnderlineStyleNone) Then s = "<u>" & s & "</u>"
End If
getHTMLFormattedString = s
End Function
To be clear, this function works only with a range containing a single cell. But it should be easy calling this function for each cell in a bigger range and concatenating the returned strings into one.
Edit by the OP:
I called the function by the below code:
Sub ReplaceFormattingTags()
Dim i As Integer, j As Integer
Dim rng As Range
Dim Txt As String
Set rng = Range("A2:C15")
For i = 1 To rng.Rows.Count
For j = 1 To rng.Columns.Count
Txt = Txt & getHTMLFormattedString(rng(i, j)) & " "
Next j
Txt = Txt & vbCrLf
Next i
Debug.Print Txt
End Sub
VBA string does not support formatting like that. It will purely take the string from the range. No formatting at all. If you want to format the string, you can not see this through msgbox.
Only way to do it would be to store it in a cell then format the cell. But then that does not give you the output in a messagebox as a formatted string.
If you are planning to then put the string in a cell with formatting, you will need to save the formatting somewhere, or copy it from the cell you got the text from. And then apply the formatting to the cell