VBA/PowerPoint: Split date-time field into lines - vba

I have a PowerPoint presentation, where I add an automatically updating date-time field to a text box (via Insert -> Text -> Date & Time, with checked "Update Automatically"). The textbox is resized so that the text (Wednesday, March 31, 2021) is split across two lines, for example:
Wednesday,
March 31, 2021
I would like to process the information line-wise, trying the following VBA:
Sub TryLines()
For Each Line In ActiveWindow.Selection.TextRange2.Lines
Debug.Print Line
Next Line
End Sub
If I call this function with the whole date-time field (distributed across two lines) selected, I get the following output:
Wednesday, March 31, 2021
Wednesday, March 31, 2021
I.e. PowerPoint recognizes that there are actually two lines, but is apparently not able to "break up" the date-time field into actual separate lines, and instead treats the date-time field as a monolith. A similar thing seems to happen for Characters.
Actual question: Is there a way to retrieve the text within a field line-wise? I would like to be independent of date format and of the actual wrapping.
Some more background, if helpful: At last, I would like to compute the polygon formed by the text-selection highlightning. Since I did not find a method to do this in TextRange2, I thought about splitting into lines and compute rectangles per line:
Sub TryToComputeLineBounds() ' call this while the date-time field is selected
For Each Line In ActiveWindow.Selection.TextRange2.Lines
Dim x(4) As Single, y(4) As Single
Line.RotatedBounds x(1), y(1), x(2), y(2), x(3), y(3), x(4), y(4)
Debug.Print Line
For i = 1 To 4
Debug.Print x(i) & " | "; y(i)
Next i
Next Line
End Sub
I realized that the measured points are the same per (what I assumed) line, and then found out that Lines does not actually give me the lines within a date-time field.

I think you're getting the Lines and Characters as a monolith because there is something special about inserted Date & Time that means it will never "break up". I tried your code with a text box that had some characters I typed in and it worked - I was able to read lines and characters one at a time.
So maybe make a temporary copy of the text box but without automatic date inserted, i.e. a Text value equivalent to the date, then use the copy to compute the polygon.

As Morboss surmised, a date field is read as one line regardless of how it appears. In the user interface, if you click on a multiline text, the insertion point appears where you click. Not so with a date: the first time you click on it the entire field is selected and no insertion point appears.
As a workaround, get the day name and date with string parsing:
Sub GetDayName()
Dim SpacePos As Long
Dim FieldText As String, DayName As String, DateValue As String
FieldText = ActiveWindow.Selection.TextRange2.Text
SpacePos = InStr(FieldText, " ")
DayName = Left(FieldText, SpacePos)
DateValue = Right(FieldText, (Len(FieldText) - SpacePos))
MsgBox DayName
MsgBox DateValue
End Sub

Related

Number Format with Thousands Separator and Decimal if Necessary

I'm trying to create a custom format such that the number will be displayed with commas as the thousands separator. Where I am struggling to find a solution (both through trial and error as well as searching) with a decimal point if the number has one, but without a decimal point if the number is whole.
Here's what I would like to achieve:
- "123" displays as "123"
- "1234" displays as "1,234"
- "1234.5" displays as "1,234.5"
- "1234.56" displays as "1,234.56"
- "1234.567" displays as "1,234.57"
Here's what I have tried so far, to no avail:
Print Format(1234, "Standard") 'Displays "1,234.00"
Print Format(1234, "#,###.##") 'Displays "1,234."
These are not the desired results, as it unnecessarily displays the decimal. How can I access the decimal point when needed, and avoid when not, all while having the thousands separator?
You may complete this task by using the custom format Function CustomFormat in Excel VBA as shown below:
Sub TestFormatString()
Debug.Print CustomFormat(123)
Debug.Print CustomFormat(1234)
Debug.Print CustomFormat(1234.5)
Debug.Print CustomFormat(1234.56)
Debug.Print CustomFormat(1234.567)
End Sub
Function CustomFormat(InputValue As Double) As String
CustomFormat = Format(InputValue, "#,###.##")
If (Right(CustomFormat, 1) = ".") Then
CustomFormat = Left(CustomFormat, Len(CustomFormat) - 1)
End If
End Function
The result shown below conforms to your requirements:
123
1,234
1,234.5
1,234.56
1,234.57
Note: as you didn't specify how to display the numbers less that 1 (for example, 0.123) then consider two possible solutions:
CustomFormat VBA Function shown above will display it as
.12
in order to display it as 0.12, just change the format mask from "#,###.##" to "#,##0.##" in CustomFormat Function, keeping the rest intact.
Hope this may help.
You can add Conditional Formatting for those with a Decimal then set the default Number Format with 0 decimals.
Add Conditional Formatting: with #,##0.## unless you want 0.5 as .5
Set Default Number Format:
Done

Word Macro for separating a comma-separated list to columns

I have a very large set of data that represents cartesian coordinates in the form x0,y0,z0,x1,y1,z1...xn,yn,zn. I need to create a new line at the end of each xyz coordinate. I have been trying to record a macro that moves a certain number of spaces from the beginning of each line, then creates a new line. This, of course, will not work since the number of digits in each xyz coordinate differs.
How can I create a macro to do this in Microsoft Word?
Try this:
Public Sub test()
Dim s As String
Dim v As Variant
Dim t As String
Dim I As Long
s = "x0,y0,z0,x1,y1,z1,xn,yn,zn"
v = Split(s, ",")
t = ""
For I = LBound(v) To UBound(v)
t = t + v(I)
If I Mod 3 = 2 Then
t = t + vbCr
Else
t = t + ","
End If
Next I
t = Left(t, Len(t) - 1)
Debug.Print t
End Sub
The Split function splits a string along the delimiter you specify (comma in your case), returning the results in a 0-based array. Then in the For loop we stitch the pieces back together, using a carriage return (vbCR) every third element and a comma otherwise.
The final (optional) step is to remove the trailing carriage return.
Hope that helps
The question placed before us was most clearly asked
“Please produce a macro sufficient to the task
I have Cartesian coordinates, a single line of these
Array them in many lines, triplets if you please!”
Instinctively we start to code, a solution for this quest
Often without asking, “Is this way truly best?”
But then another scheme arises from the mind
That most venerated duo: Word Replace and Find
Provide the two textboxes each an encantation
Check the Wildcard option and prepare for Amazation!
Forgive me!
In Word open Find/Replace
Click the More button and check the Use wildcards box
For Find what enter ([!,]{1,},[!,]{1,},[!,]{1,}),
For Replace with enter \1^p
Use Find Next, Replace and Replace All as usual
How it works
With wildcards, [!,]{1,} finds one or more chars that are NOT commas. This idiom is repeated 3 times with 2 commas separating the 3 instances. This will match 3 comma-delimited coordinates. The whole expression is then wrapped in parentheses to created an auto-numbered group (in this case Group #1). Creating a group allows us to save text that matches the pattern and use it in the Replace box. Outside of the parentheses is one more comma, which separates one triplet of coordinates from the next.
In the Replace box \1 retrieves auto-numbered group 1, which is our coordinate triplet. Following that is ^p which is a new paragraph in Word.
Hope that helps!

How to use UserForm Values for multiple things

I have UserForm1 which is a multipage userform and I am trying to access the information that was gathered through the form in a sub located in Module1. This sub will need to access several different values and do different things with those values so this is going to be a multipart question.
I have the below code in which I attempt to use one of the values as the upper limit of a For Next Loop. However the current problem is that when the code reaches this line it jumps to the Userform_Initialize routine.
For X = 1 To UserForm1.LocalOffer.Value
Second part of this question comes from inside the For Next loop from above. Where I have the below code. Which would ideally allow me to cycle through a series of similarly named Textboxes from the userform. Not even sure if that will work as the code keeps breaking before getting to that part.
Range("B" & X).Value = UserForm1.Controls("LocalTier" & Tier).Value
Last Part of this question if I have a Textbox in the userform that contains a date in the format 1/18/2015 is there a way for me to grab just a portion of that date say for instance just the Day or just the last digit of the year?
I am using Excel 2013 but the file will be ran on Excel 2007
Edit:
Turns out that problem 1 was fixed by not closing the userform with the X button but instead adding a line to hide the userform when you hit the last button. As it turns out my code for the second question worked just fine once i got past that. Only question left is the last one which I have no ideas on.
As from the comments, I see you don't need anymore to know about points 1 and 2, I will hence limit my answer to the point 3.
Last Part of this question if I have a Textbox in the userform that contains a date in the format 1/18/2015 is there a way for me to grab just a portion of that date say for instance just the Day or just the last digit of the year?
You can use either string manipulation, or date conversion.
Let's assume the Textbox is called myDateTextbox
String manipulation
Among the string manipulators that VBA provides, I would cite Left() and Right().
For example:
last_digit_of_the_year = Right(myDateTextbox.Text, 1)
will return you the last character of the string. On the other hand:
first_digit = Left(myDateTextBox.Text,1)
will return you the first digit of the string.
You can use the Len(myDateTextBox.Text) built-in to return the current length of the string.
Date conversion
You can simply convert your string into date using the CDate() function. Please note this function will return an error if you pass an invalid string. If your textbox contains 24/01/1990, you can first convert the string into a date:
myDate = CDate(myDateTextBox.Text)
Hence, you can retrieve day, month or year like this:
myYear = Year(myDate)
myMonth = Month(myDate)
myDay = Day(myDate)
Please note that CDate recognizes date formats according to the locale setting of your system.. Hence, if the format in the TextBox is not the same than the one of your system, then consider manipulating the string before to adapt it to the proper format. For example, if your system has settings DD/MM/YYYY and your textbox shows a MM/DD/YYYY type, you can "adjust it" as follows:
wrongFormat = myDateTextBox.Text
splittedDate = Split(wrongFormat,"/")
goodFormat = splittedDate(1) & "/" & splittedDate(0) & "/" splittedDate(2)
If wrongFormat was 1/18/2014 but your system would like to read it as 18/1/2014, it's now fine because goodFormat will be equal to 18/1/2014 after the split and re-build.

Count a specific word using a Function ans a Sub

In VB.net, I want to make a counting program using a Function and a Sub.
There is a textbox to input a date and a button to exercise the programme in Form1.
I have a txt file which was extracted from MS-Excel with sequential date of time at its column A.
And from that txt file, I want to count the number of date(Actually string) such as "18-Jun-12".
The answer showing the count should be in the format of msgbox in the Sub.
I really have no idea how to link a Function and a Sub using variable, because I am just beginner.
Any help will be gratefully accepted.
If the fields are delimited by comma you must be careful since the field itself could contain a comma. Then you cannot differentiate between the value and the delimiter. You either could enclose the fields with quotes to mask them. But then you should use an available CSV parser anyway.
If the values never contain comma and you want a simple solution use File.ReadLines or File.ReadAllLines to read the lines and String.Split to get all fields per line.
Here's a simple approach using a little bit of LINQ to count all lines which contain the searched date (as string):
Dim linesWithThatDate = From line in File.ReadLines("Path to File")
Where line.Split(","c)(0).Trim() = "18-Jun-12"
Dim count = linesWithThatDate.Count()
As an aside, if the user must enter a date you could use a DateTimePicker control instead. Then you should also use Date.Parse(line.Split(","c)(0).Trim()) or Date.TryParse to get a real date.

Date Formatting in Excel VBA

I have written a long procedure in VBA to manipulate a data set. Part of this involves using and formatting dates, and I can't get it to work properly.
The initial data as downloaded has dates in the format "yyyy-mm-ddThh:mm:ssZ" - e.g. 2014-12-11T04:59:00Z.
I then convert these into a date in UK format of "dd/mm/yyyy". Looping over all relevant cells, I use the following method:
initial_date = Range("A1").Value
Dim publish_date As Date
publish_date = DateValue(Mid(initial_date,9,2) & "/" & Mid(initial_date,6,2) & "/" & Mid(initial_date,1,4))
Range("A1").Value = publish_date
This seems to work fine. The cell automatically changes format to "Date" and when I calculate the difference between these dates and dates in another column, it works fine.
I then pick up these dates again and add to an array:
feed(1, 8) = Range("A1")
and then transfer this value into another array:
new_array(7, 1) = feed(1, 8)
Finally, I insert the value from the new array into a different cell. Having used UK date formatting thus far, I now want this value to display in the form "mm/dd/yyyy".
Range("E1") = new_array(7, 1)
Range("E1").NumberFormat = "mm/dd/yyyy"
This is where it goes wrong.
Running the code as above, the dates are all displayed as "dd/mm/yyyy" format. Excel changes the format of the cells to "custom". Finding the difference between these and other dates works, so the data seems to be stored correctly but not displaying as I want.
If I change the code to
Range("E1") = new_array(7, 1)
Range("E1").NumberFormat = "dd/mm/yyyy"
the dates still do not display correctly. Dates which can be written either way around (i.e. day is equal to or less than 12) display correctly, but are in fact the wrong date. i.e. 2014-12-11T04:59:00Z displays as 12/11/2014 which is what I want, but Excel thinks the date is the 12th November instead of 11th December. Dates such as 29/09/2014 which cannot be written both ways round display in UK format, but are not recognised properly by Excel which thinks the long date should be "29/09/2014" instead of "29 September 2014".
When I remove the formatting line completely, the results are the same.
I'm sorry for the rather long-winded explanataion, but there's clearly something I'm not understanding about how Excel and VBA handle, store and format dates. If anyone could enlighten me what's going wrong, I'd really appreciate it!
(Note, in all the code snippets above, where I quote e.g. Range("A1") this is shorthand. There is in fact a lot more code involved in looping and selecting values, but I know this works, so I am not concerned. The extracts above just demonstrate what happens for the first value in each loop.)
try
Range("E1").NumberFormat = "mm/dd/yyyy"
Range("E1") = Format(new_array(7, 1), "mm/dd/yyyy")