Creating a custom date based counter (on yearly basis, on monthly basis, ...) - moqui

I need to prepare a "counter" for creating IDs based on a specific mask with automatically incremented counter (yearly based). Something like "10${myYear}/${myCounter(myYear)}-FP" where the ID for the first document in 2016 would be 1016/001-FP:
"10" is a fix string that does not change,
"16" is the the yy of current year > ${myYear},
"/" is a fixed string again,
"001" is the first item for the actual year > ${myCounter(myYear)} - the counter would start from 1 on the beginning of each year and automatically incremented each time a new item is created (pulled from),
"-FP" is again a fixed string.
Does counter-handler have to be custom coded or is there anything similar included?

Related

In excel VBA, I am looking for VBA code that adds a new line item with the latest month end each time the spreadsheet opens

I currently have a spreadsheet that has individual line items for each month end. Starting in A1, 1/31/2021 and A5, 5/31/2021 for example. My goal is, each month when I open the spreadsheet, a new line item is created for that month; so if it's 5/21/2021 and I open the spreadsheet, it will create a line item with 5/31/2021. Is it possible to include logic that checks the current month I'm in and will open add a line item if it's relevant for the appropriate month?
Screenshot/here refer:
(note - for security reasons, linked sheet above has not VB code - this needs to be built in as described below).
High level
This soln. requires following: 2 named ranges, macro-enabled workbook. Office 365 not necessary.
Setup
Enter any date you wish in column A (max capacity = 100)
Ranges
Create named formula: Formulas | Name Manager | New… set name = 'dates'; enter formula: =$A$1:OFFSET($A$1,COUNTA(1,1000)-1,0,1,1)
(This is a dynamic (automatically grows to accommodate your list of dates in column A)
As for 2) but with following: name : 'Required' (w/ apostrophes), formula = =IFERROR(IF(YEAR(INDEX(dates,MATCH(MONTH(TODAY()),MONTH(dates),0)))=YEAR(TODAY()),0,1),1)
(this creates a formula that checks whether any of the dates in col A already have the current month. i.e. 'Required' = 0 if month already exists (for current year); else 1 returned)
VB
Let the fun begin!
Alt + F11 (open VB for Excel running on Windows)
Locate your file in the Project Explorer (typically default window pane on left hand side; if no such pane, then select from the upper ribbon/menu bar: View | Project Explorer:
Double click the component entitled 'ThisWorkbook' to reveal a new window pane on the right-hand side of the VB window.
The remaining operations appertain to the VB window pane on the Right Hand Side (RHS)...
There are two menu bars with drop-down functionality at the top of the VB-code pane:
Left drop-down / Right drop-down - select respective drop-downs as 'Workbook' and 'Open' respectively, then enter the code per below screenshot (code replicated here for convenience):
Code
Private Sub Workbook_Open()
REQ = Application.Evaluate("Required")
Range("f5").Value = REQ
If REQ = 1 Then
new_date = Format(Date, "dd/mm/yyyy")
Sheets("68516961").Range("dates").Offset(1).Value = new_date
End If
End Sub
Voila! You're all set to go! I tested a couple of times and all appears to be working fine. fyi - don't forget to save as macro-enabled workbook (I prefer .xlsb files as the typically have half the file size compared to .xlsm - the one exception I'm aware of is if there is an SQL connection - in which case it's about the same size as the .xlsm counterpart)...
Functionality:
Every time you open the workbook, the VB code is run - it checks to see if there are any dates that comprise the same month and year as the day your opening the file; if not, the date of 'that day' is automatically populated at the bottom of any existing list of dates in A:A. This gives you the freedom of being able to include other / manually entered dates or otherwise between successive VB created date appended values.
Appendices
Creating named ranges:

Parsing formula to cell using VBA

Trying to place formula:
IF(TEXT(A4,”ddd”)=“Fri”,IF(TEXT(B4-INT(B4),”hh:mm:ss”)>=TEXT(TIME17,0,0 "),”hh:mm:ss”),”flag”," "),IF(TEXT(A4,”ddd”)=“Sat”,”flag”,IF(TEXT(A4,”ddd”)=“Sun”,”flag”,IF(TEXT(A4,”ddd”)=“Mon”,IF(TEXT(B4-INT(B4),”hh:mm:ss”)<=TEXT(TIME("8,30,0"),”hh:mm:ss”),”Flag”,"”)))))
into cell but using CHR(34) instead of " makes it too long in character length. Then tried using defined name and in "refers to:" used the evaluate formula i. e. =evaluate("T1"); T1 had the text version of the formula as above.
Create Date Create Time
03/05/17 07:28 AM
09/05/17 07:32 AM
13/05/17 07:20 AM
16/05/17 04:57 PM
17/05/17 10:17 AM
The spreadsheet contains date in column A and date-time formatted as time in column B. I am working out if the particular line is between the hours of Fri 5pm and Mon 8:30am.
If you just want a shorter formula, you could use
=IF(OR(WEEKDAY(A4,2)>5,AND(WEEKDAY(A4,2)=5,B4>17/24),AND(WEEKDAY(A4,2)=1,B4<8.5/24)),"Flag","")
In VBA, that could be coded as (for instance):
Range("C4").Formula = "=IF(OR(WEEKDAY(A4,2)>5,AND(WEEKDAY(A4,2)=5,B4>17/24),AND(WEEKDAY(A4,2)=1,B4<8.5/24)),""Flag"","""")
The above formulas assume that column B just contains the time, but if it contains the date and time, then you should use:
=IF(OR(WEEKDAY(B4,2)>5,AND(WEEKDAY(B4,2)=5,MOD(B4,1)>17/24),AND(WEEKDAY(B4,2)=1,MOD(B4,1)<8.5/24)),"Flag","")
In VBA, that could be coded as (for instance):
Range("C4").Formula = "=IF(OR(WEEKDAY(B4,2)>5,AND(WEEKDAY(B4,2)=5,MOD(B4,1)>17/24),AND(WEEKDAY(B4,2)=1,MOD(B4,1)<8.5/24)),""Flag"","""")
Correcting your original formula to what I think you intended it to be, would give you VBA code of (for instance):
Range("C4").Formula = "=IF(TEXT(A4,""ddd"")=""Fri"",IF(TEXT(B4-INT(B4),""hh:mm:ss"")>=TEXT(TIME(17,0,0),""hh:mm:ss""),""flag"","" ""),IF(TEXT(A4,""ddd"")=""Sat"",""flag"",IF(TEXT(A4,""ddd"")=""Sun"",""flag"",IF(TEXT(A4,""ddd"")=""Mon"",IF(TEXT(B4-INT(B4),""hh:mm:ss"")<=TEXT(TIME(8,30,0),""hh:mm:ss""),""Flag"","""")))))"
There are several things in that that could easily be simplified, e.g.:
TEXT(TIME(17,0,0),""hh:mm:ss"") could be more simply written as "17:00:00" (it's a fixed time that is going to have a fixed result), and
TEXT(B4-INT(B4),""hh:mm:ss"") could be simplified to TEXT(B4, ""hh:mm:ss"") (the time string is going to be the same whether you calculate it on the specific day, or whether you calculate it on 0 January 1900).

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.

VB.NET CHART- Display a subset of the total data points

VB 2008
.NET FRAMEWORK 3.5
MSCHART - FASTLINE CHART TYPE
Is it possible to have an MS Chart control contain 20,000 data points, but only show the last 100?
I know that I can select the last 100 from my datatable and use it as a datasource.
Chart1.DataSource = cMs2.dsData.Tables("readings").Select(wFilter, wSort).Take(100)
That's not what I want.
I know that I can populate an array or collection with the last 100 data points and use it as a data source.
Chart1.Series("readings").Points.DataBindXY(colCtr, colReadings)
That's not what I want.
I need to do 1 of 2 things:
Manually add data points and be able to show only the last 100 or last 1000 of them that just came in. This must be done without re-populating the chart. Just show a portion of the complete set of data points.
wSample = wSample + 1
Chart1.Series("readings").Points.AddXY(wSample, wReading)
Chart1.Series("readings").SHOWONLYTHELAST100DATAPOINTSWITHOUTCLEARING
Initialize a chart with a certain number of the total readings with a databind, then manually add new data points one at a time while removing the oldest data point. For example, initialize the chart with 100 data points, then add a new data point, remove the first data point, getting us back to 100. (I'm successfully doing this one, except the chart doesn't behave like I expect. The chart grows, remaining blank/empty where the 'removed' data points were. I do chart.update but it doesn't refresh it.) Note that I am allowed to take more time to initialize the chart (clear/populate), I don't have that time to do it as each new data point comes in.
wSample = wSample + 1
Chart1.Series("readings").Points.AddXY(wSample, wReading)
If Chart1.Series("readings").Points.Count > 100 Then
Chart1.Series("readings").Points.RemoveAt(0)
Chart1.Update()
End If
NOTE: Doing a process that causes me to have to clear and rebind the data to handle the addition of a single data point causes me problems because it takes too long. I'm just looking for the quickest, most efficient way to handle this. Thank you for taking the time to read this...!
You can manually set the Minimum and Maximum values of each axis by modifying the .Minimum and .Maximum values of the axes like
Chart1.ChartAreas(0).AxisX.Minimum = 100 'Example value
Chart1.ChartAreas(0).AxisX.Minimum = 200 'Example value
As discussed in the comments to your question you can either use your method #2 (add datapoint and delete datapoint index 0 and then select the new minimum and maximum X-Value from the series with LinQ:
Chart1.ChartAreas(0).AxisX.Minimum = (From p As DataVisualization.Charting.DataPoint In Chart1.Series(0).Points Select p.XValue).Min
Chart1.ChartAreas(0).AxisX.Maximum = (From p As DataVisualization.Charting.DataPoint In Chart1.Series(0).Points Select p.XValue).Max
or you can, as you have now done, just set the minimum value to a X-value some points before the last point.

Creating a Macro in Excel 2007 to extract moving data

I have one sheet which is comprised of data that was imported from a web page. In a second sheet I have a cell asking for min price and max price which comes from the imported data. The issue is that the data can move to different cells when it's refreshed so my code needs to look for some specific wording to find the prices that I need rather than just directing it to the same cell each time
The info in the imported data sheet which I need to extract from will always be in this string of text which will always be found somewhere between row 15-35 but will move when the website is refreshed. The 1st number (71.00) needs to be extracted to another sheet in a cell asking for min price while the second number (75.00) is the max price. These prices can change so I can just look for those numbers and extract them.
SLAUGHTER BULLS: Yield grade 1-2 1000-1500 lbs
1500-2000 lbs 71.00-75.00.
Could someone please help me with the coding for this macro?
Use the InStrRev function (similar to the LastIndexOf function in .NET) to find the last index of "lbs" in the test string.
lastIndex = InStrRev(testString, "lbs", 1, 1)
Then search from that last index to the end of the string spliting on the -
splitArray = Split(Mid(testString, lastIndex, Len(testString) - lastIndex), "-", 1)
The lowest value will be in splitArray(0) and the upper value will be in splitArray(1) assuming a zero indexed array.