Re: Create Popup alert Form without buttons (like outlook desktop alert)
Give my sample file a try, it will show you how to use the alert.
Re: Create Popup alert Form without buttons (like outlook desktop alert)
Give my sample file a try, it will show you how to use the alert.
Re: Create Popup alert Form without buttons (like outlook desktop alert)
I noticed you copied the code in two separate places. The code should just be located in modAlert not in Module1. To use the notification in Module1 you would type modAlert.Alert(text,title,seconds).
What do you mean by not work? Is it erroring?
Cheers,
MJ
EDIT: Try my sample file
[ATTACH=CONFIG]40384[/ATTACH]
Re: Maxif, minif and stdevif functions using wildcard
My pleasure,
Cheers,
MJ
Re: Maxif, minif and stdevif functions using wildcard
Hi JamesMunroe,
Add the following two subroutines to your module, one is for population and one is for sample standard deviation.
Cheers,
MJ
Public Function STDEVSIF(rngEvaluate As Range, _
strCondition As String, _
Optional rngValues As Range = Nothing) As Variant
Dim varValue As Variant
Dim bolValueSet As Boolean
Dim intRow As Integer
Dim intCol As Integer
Dim dblAvg As Double
Dim lngCnt As Long
If (rngValues Is Nothing) Then Set rngValues = rngEvaluate
bolValueSet = False
If Not RangesOK(rngEvaluate, rngValues) Then
'Return an error value
varValue = "Error in range selection"
Else
'If the ranges are not identically sized can not get this far!
dblAvg = Application.WorksheetFunction.AverageIf(rngEvaluate, strCondition, rngValues)
lngCnt = Application.WorksheetFunction.CountIf(rngEvaluate, strCondition)
For intRow = 1 To rngEvaluate.Rows.Count
For intCol = 1 To rngEvaluate.Columns.Count
If Application.CountIf(rngEvaluate(intRow, intCol), strCondition) = 1 Then
varValue = varValue + (rngValues(intRow, intCol) - dblAvg) ^ 2
End If
Next intCol
Next intRow
varValue = Sqr(varValue / (lngCnt - 1))
End If
STDEVSIF = varValue
End Function
Public Function STDEVPIF(rngEvaluate As Range, _
strCondition As String, _
Optional rngValues As Range = Nothing) As Variant
Dim varValue As Variant
Dim bolValueSet As Boolean
Dim intRow As Integer
Dim intCol As Integer
Dim dblAvg As Double
Dim lngCnt As Long
If (rngValues Is Nothing) Then Set rngValues = rngEvaluate
bolValueSet = False
If Not RangesOK(rngEvaluate, rngValues) Then
'Return an error value
varValue = "Error in range selection"
Else
'If the ranges are not identically sized can not get this far!
dblAvg = Application.WorksheetFunction.AverageIf(rngEvaluate, strCondition, rngValues)
lngCnt = Application.WorksheetFunction.CountIf(rngEvaluate, strCondition)
For intRow = 1 To rngEvaluate.Rows.Count
For intCol = 1 To rngEvaluate.Columns.Count
If Application.CountIf(rngEvaluate(intRow, intCol), strCondition) = 1 Then
varValue = varValue + (rngValues(intRow, intCol) - dblAvg) ^ 2
End If
Next intCol
Next intRow
varValue = Sqr(varValue / lngCnt)
End If
STDEVPIF = varValue
End Function
Display More
Re: If a cell meets a condition, copy that row to another worksheet
It's my pleasure, I'm glad you're finding it useful and learning from it. If you have any questions as you go through the code, feel free to ask.
Cheers,
MJ
Re: MS XLS function to calculate centroid of a polygon
My Pleasure!
Cheers,
MJ
Re: Maxif, minif and stdevif functions using wildcard
Hi JamesMunroe,
Check out this thread, it should prove useful.
http://www.ozgrid.com/forum/showthread.php?t=26192&page=1
Cheers,
MJ
Re: Create Popup alert Form without buttons (like outlook desktop alert)
Hi udhaya_k,
I figured it out! Import the following module into your VBE and it will expose a subroutine called Alert (or modAlert.Alert) which has as arguments: (Message,Title,Number of seconds before it disappears).
If the number of seconds is 0 or missing it will stay on screen until you click OK. This does exactly as you wish, it will pop up on top of any open application and will run in a separate thread than your macro so it will not halt your code at all (except for the slight time it takes to run its code of course).
[ATTACH=CONFIG]40359[/ATTACH]
IMPORTANT: In Excel 2002 and newer you will have to explicitly trust access to your VBA Projects. Go to Tools, Macro, Security. Click on the 2nd tab: Trusted Publishers. In the lower left, choose Trust Access to Visual Basic Project. In Excel 2007, Go to Office Icon, Excel Options, Trust Center, Trust Center Settings, Macro Settings, and choose Trust access to the VBA project object model.
If you have any questions, feel free to ask.[ATTACH=CONFIG]40377[/ATTACH]
Cheers,
MJ
EDIT: Changed subroutine in modAlert as I forgot to do some cleaning up after the code was run, this should fix that. Replace subroutine CreateAlertObject with this:
Public Sub CreateAlertObject(sText As String, sTitle As String, lNumSeconds As Long)
CreateObject("Wscript.Shell").popup sText, lNumSeconds, sTitle, vbSystemModal + 64
ThisWorkbook.Close False
Application.Quit
End Sub
or use this updated .bas file:
[ATTACH=CONFIG]40377[/ATTACH]
Re: Create Popup alert Form without buttons (like outlook desktop alert)
Hi udhaya_k,
Well, I've been working on this for a bit now (it's actually quite interesting). I have managed two methods: the first isn't exactly what you want and the second one I am in the process of coding (deceivingly difficult). The first method is this:
The '3' represents how many seconds you want it stay before disappearing. The problem with this is that your code will pause until the popup disappears.
For the second method I have been attempting to create my own alert with the functionality you described. Essentially what I did was create a modeless userform consisting of just a Label control, in a subroutine I Load the form, pass it variables (such as text, etc...) and then show it. At this point the activation of the form calls a few Windows API that find its window handle and slowly increment its transparency to create the fade in effect. Up to this point everything is golden, now comes the trouble. To create the disappear after N seconds functionality I thought of adding an Application.OnTime event inside the subroutine to Unload the form (which fades it out), this is fine except for this one point:
Excel is a single threaded application when performing macros or user actions, if a macro is running the user is blocked out and vice versa. So, even though the Application.OnTime is created in a separate thread it's attempting to run the Unload routine in the macro thread and thus has to wait until the initial code has fully completed before unloading the form. I can't seem to find a way to make the OnTime method pause the initial code and take precedence (nor do I think it's possible). The only way I can think of that might work (and I stress might) is to make a COM Interface that when connected to can create the popup on its own thread server side (which can still be local keep in mind).
I'll give it a try at some point, I can't say how long it will take as I'd have to look at it a bit more first. Hopefully the first method is good enough. If someone is interested in my half finished Userform popup I can post it. Otherwise if you have any question, feel free to ask.
Cheers,
MJ
Re: Create Popup alert Form without buttons (like outlook desktop alert)
Hi udhaya_k,
So if I understand correctly you will be running a macro in excel and while it is running you're going to working in some other application. What you want to happen is at certain points in your macro code you want an alert to pop-up somewhere on the screen that does not require feedback from the user (ie will not stop the code from continuing). If possible, would you like it to disappear after some time or not?
Is this correct?
Cheers,
MJ
Re: Create new Worksheet from List and combine worksheets in different folders
Hi Chris,
Paste the following code into a module in a new workbook, hopefully it's what was intended. The code assumes that the folders already exist and it will overwrite any previous file for that student in '\Grade Sheets'. If you have any questions, feel free to ask.
Cheers,
MJ
Sub Create_NameBooks()
Dim sFilePath As String
Dim oGradeSheet As Worksheet
Dim oNameSheet As Worksheet
Dim oWB As Workbook
Dim oWS As Worksheet
Dim oCell As Range
Dim sName As String
sFilePath = "C:\Chris\Office 2010\"
Set oWB = Application.Workbooks.Open(sFilePath & "Names\Names.xlsx")
Set oNameSheet = oWB.Worksheets("Names")
Set oWB = Application.Workbooks.Open(sFilePath & "GradeBook.xlsx")
Set oGradeSheet = oWB.Worksheets("Lab #")
ThisWorkbook.Activate
Application.ShowWindowsInTaskbar = False
Application.ScreenUpdating = False
For Each oCell In oNameSheet.Range(oNameSheet.Cells(2, 1), oNameSheet.Cells(2, 1).End(xlDown))
sName = oCell.Value
Set oWB = Application.Workbooks.Add
oGradeSheet.Copy Before:=oWB.Worksheets(1)
Application.DisplayAlerts = False
With oWB
.Worksheets(oWB.Worksheets.Count).Delete
.Worksheets(oWB.Worksheets.Count).Delete
.Worksheets(oWB.Worksheets.Count).Delete
.Close True, sFilePath & "Grade Sheets\" & sName & ".xlsx"
End With
Application.DisplayAlerts = True
Next oCell
oGradeSheet.Parent.Close False
oNameSheet.Parent.Close False
Application.ShowWindowsInTaskbar = True
Application.ScreenUpdating = True
End Sub
Display More
Re: Vlookup
Yup, MATCH/INDEX will work... or for a quick and dirty method you can just copy and paste the 'Payee' column to the left of Date.
Cheers,
MJ
Re: Create new Worksheet from List and combine worksheets in different folders
Hi Chris,
Just to clarify a few things. Will the entire Gradebook (say sheet1) be copied into each student's spreadsheet or will it be the part of the Gradebook that represents that student's grades? Example workbooks would be very useful in this situation (with names and grades changed obviously =P ).
Cheers,
MJ
Re: MS XLS function to calculate centroid of a polygon
Hi rcpomp,
I'm not sure why you're getting negative values in that case, I can't seem to reproduce the situation. If you give me the coordinates you're using that might help. Otherwise, I've updated the code so that it is used as a worksheet function now. It has five possible results:
'=Centroid(RANGE, "x")' will give the x-coordinate
'=Centroid(RANGE, "y")' will give the y-coordinate
'=Centroid(RANGE, "area")' will give the absolute area
'=Centroid(RANGE, "sarea")' will give the signed area
'=Centroid(RANGE)' will give the coordinate pair to 3 decimal places
Hope this helps and if you have any question, feel free to ask.
Cheers,
MJ
Function Centroid(oRng As Range, Optional sType As String) As Variant
Dim vCoords As Variant
Dim vRow() As Variant
Dim i As Long
Dim Area As Double
Dim xPos As Double, yPos As Double
vCoords = oRng.Value
ReDim vRow(LBound(vCoords, 2) To UBound(vCoords, 2))
For i = LBound(vCoords, 2) To UBound(vCoords, 2)
vRow(i) = vCoords(1, i)
Next i
vCoords = AddRow(vCoords, vRow)
Area = CalcArea(vCoords) 'Note that this is a signed area; if the points are numbered in clockwise order then the area will have a negative sign
xPos = CalcxPos(vCoords, Area)
yPos = CalcyPos(vCoords, Area)
If UCase(sType) = "X" Then
Centroid = xPos
ElseIf UCase(sType) = "Y" Then
Centroid = yPos
ElseIf UCase(sType) = "AREA" Then
Centroid = Abs(Area)
ElseIf UCase(sType) = "SAREA" Then
Centroid = Area
Else
Centroid = "(" & Round(xPos, 3) & "," & Round(yPos, 3) & ")"
End If
End Function
Private Function CalcxPos(vCoords As Variant, Area As Double) As Double
Dim i As Long
For i = 1 To UBound(vCoords, 1) - 1
CalcxPos = CalcxPos + (vCoords(i, 1) + vCoords(i + 1, 1)) * (vCoords(i, 1) * vCoords(i + 1, 2) - vCoords(i + 1, 1) * vCoords(i, 2))
Next i
CalcxPos = CalcxPos / (6 * Area)
End Function
Private Function CalcyPos(vCoords As Variant, Area As Double) As Double
Dim i As Long
For i = 1 To UBound(vCoords, 1) - 1
CalcyPos = CalcyPos + (vCoords(i, 2) + vCoords(i + 1, 2)) * (vCoords(i, 1) * vCoords(i + 1, 2) - vCoords(i + 1, 1) * vCoords(i, 2))
Next i
CalcyPos = CalcyPos / (6 * Area)
End Function
Private Function CalcArea(vCoords As Variant) As Double
Dim i As Long
For i = 1 To UBound(vCoords, 1) - 1
CalcArea = CalcArea + vCoords(i, 1) * vCoords(i + 1, 2) - vCoords(i + 1, 1) * vCoords(i, 2)
Next i
CalcArea = 0.5 * CalcArea
End Function
Private Function AddRow(InputArr As Variant, vRow As Variant) As Variant
Dim vTemp As Variant
Dim i As Long
If LBound(vRow) <> LBound(InputArr, 2) Or UBound(vRow) <> UBound(InputArr, 2) Then AddRow = 0: Exit Function
vTemp = TransposeArray(InputArr)
ReDim Preserve vTemp(LBound(vTemp, 1) To UBound(vTemp, 1), LBound(vTemp, 2) To UBound(vTemp, 2) + 1)
vTemp = TransposeArray(vTemp)
For i = LBound(vTemp, 2) To UBound(vTemp, 2)
vTemp(UBound(vTemp, 1), i) = vRow(i)
Next i
AddRow = vTemp
End Function
Private Function TransposeArray(InputArr As Variant) As Variant
Dim RowNdx As Long
Dim ColNdx As Long
Dim LB1 As Long
Dim LB2 As Long
Dim UB1 As Long
Dim UB2 As Long
Dim OutputArr() As Variant
LB1 = LBound(InputArr, 1)
LB2 = LBound(InputArr, 2)
UB1 = UBound(InputArr, 1)
UB2 = UBound(InputArr, 2)
ReDim OutputArr(LB2 To LB2 + UB2 - LB2, LB1 To LB1 + UB1 - LB1)
For RowNdx = LB2 To UB2
For ColNdx = LB1 To UB1
OutputArr(RowNdx, ColNdx) = InputArr(ColNdx, RowNdx)
Next ColNdx
Next RowNdx
TransposeArray = OutputArr
End Function
Display More
Re: If a cell meets a condition, copy that row to another worksheet
Hi stickyfeet,
So I've altered the code a bit to make it a little more general and customizable. Firstly to answer your question:
Quote
I've been looking at 'lLocation' as this is where it gets the value from the combobox, then trying to work out how/where it determines which column to look at.
The code was choosing which column to look at on this line:
The '1' means it's checking against the first column in vData which is the array created from the data range. Also, lLocation was getting its value from the rightmost character of your combobox because of how the values were hardcoded in, this isn't really necessary as you'll see in the updated code.
So, I changed the code so that it lets you choose which column you would like to filter on and then dynamically updates the combobox with a unique and somewhat sorted (works kind of odd on text) list of values from that column. The subroutines to create the unique list and sort it are at the bottom (some of my favourites).
I also changed two more things:
So here's a copy of the code to look at but I changed your Userform a bit to allow for my changes so I'll also include the .frm and .frx files so you can just import it into your spreadsheet. If you have any questions, feel free to ask.
Cheers,
MJ
[ATTACH=CONFIG]40333[/ATTACH]
Option Explicit
Dim lColumn As Long
Private Sub cmdCreate_Click()
Dim lRow As Long, lCol As Long
Dim lInsertRow As Long
Dim oDetailSheet As Worksheet, oReportSheet As Worksheet
Dim vTestValue As Variant
Dim vData As Variant
Dim vReportData() As Variant
Set oDetailSheet = Sheet1 'Set to the detail sheet
Set oReportSheet = Sheet2 'Set to the report sheet
vTestValue = cmbReportType.Value
If LastRow(oDetailSheet) < 3 Then Unload Me: Exit Sub 'Unload and Exit if there are no rows in data
vData = oDetailSheet.Range(oDetailSheet.Cells(3, 1), oDetailSheet.Cells(3, 1).End(xlDown).End(xlToRight)).Value 'Store relevant data in array (Note: You might want to hardcode the fact that there are 4 columns)
If LastRow(oReportSheet) > 2 Then oReportSheet.Range(oReportSheet.Cells(3, 1), oReportSheet.Cells(3, 1).End(xlDown).End(xlToRight)).EntireRow.Delete 'Clear relevant area in Report sheet
lInsertRow = 0
For lRow = LBound(vData, 1) To UBound(vData, 1)
If CStr(vData(lRow, lColumn)) = CStr(vTestValue) Then
lInsertRow = lInsertRow + 1
ReDim Preserve vReportData(1 To UBound(vData, 2), 1 To lInsertRow) 'Array is transposed as you can only alter the last dimension of an array while preserving
For lCol = LBound(vData, 2) To UBound(vData, 2)
vReportData(lCol, lInsertRow) = vData(lRow, lCol)
Next lCol
End If
Next lRow
TransposeArray2D vReportData
oReportSheet.Range(oReportSheet.Cells(3, 1), oReportSheet.Cells(3, 1)).Resize(UBound(vReportData, 1), UBound(vReportData, 2)).Value = vReportData
Unload Me
End Sub
Private Sub UserForm_Initialize()
Dim oDetailSheet As Worksheet
Dim vColNames() As Variant
Set oDetailSheet = Sheet1
vColNames = oDetailSheet.Range(oDetailSheet.Cells(2, 1), oDetailSheet.Cells(2, 1).End(xlToRight)).Value
TransposeArray2D vColNames
cmbTestCol.List = vColNames
End Sub
Private Sub cmbTestCol_Change()
Dim oDetailSheet As Worksheet
Dim vReportTypes() As Variant
Set oDetailSheet = Sheet1
lColumn = cmbTestCol.ListIndex + 1
vReportTypes = UniqueItems(oDetailSheet.Range(oDetailSheet.Cells(3, lColumn), oDetailSheet.Cells(2, lColumn).End(xlDown)).Value, True)
cmbReportType.List = vReportTypes
End Sub
Private Function LastRow(oWS As Worksheet)
LastRow = oWS.UsedRange.Rows.Count
Do Until WorksheetFunction.CountA(oWS.Rows(LastRow)) <> 0 Or LastRow = 1
oWS.Rows(LastRow).EntireRow.Delete
LastRow = oWS.UsedRange.Rows.Count
Loop
End Function
Private Sub TransposeArray2D(ByRef InputArr As Variant)
Dim lRow As Long, lCol As Long
Dim vTemp() As Variant
If Not IsArray(InputArr) Then Exit Sub
ReDim vTemp(LBound(InputArr, 2) To UBound(InputArr, 2), LBound(InputArr, 1) To UBound(InputArr, 1))
For lRow = LBound(vTemp, 1) To UBound(vTemp, 1)
For lCol = LBound(vTemp, 2) To UBound(vTemp, 2)
vTemp(lRow, lCol) = InputArr(lCol, lRow)
Next lCol
Next lRow
InputArr = vTemp
End Sub
Private Function UniqueItems(ByRef ArrayIn, Optional ByVal Sort As Boolean = True) As Variant
' Accepts an array or range as input
Dim Unique() As Variant ' array that holds the unique items
Dim Element As Variant
Dim i As Long
Dim FoundMatch As Boolean
Dim NumUnique As Long
' Loop thru the input array
For Each Element In ArrayIn
FoundMatch = False
' Has item been added yet?
For i = 1 To NumUnique
If Element = Unique(i) Then
FoundMatch = True
Exit For '(exit loop)
End If
Next i
' If not in list, add the item to unique list
If Not FoundMatch Then
NumUnique = NumUnique + 1
ReDim Preserve Unique(1 To NumUnique)
Unique(NumUnique) = Element
End If
Next Element
' Assign a value to the function
If Sort = True Then QuickSort Unique
For i = 1 To NumUnique
If IsEmpty(Unique(i)) Then Unique(i) = "#Empty#"
Next i
UniqueItems = Unique
End Function
Private Sub QuickSort(ByRef lngArray() As Variant, Optional ByRef swapArray As Variant)
Dim iLBound As Long
Dim iUBound As Long
Dim iTemp As Variant, iTemp2 As Variant
Dim iOuter As Long
Dim iMax As Long
iLBound = LBound(lngArray)
iUBound = UBound(lngArray)
If Not IsMissing(swapArray) Then If LBound(swapArray) <> iLBound Or UBound(swapArray) <> iUBound Then Err.Raise 9
'Dont want to sort array with only 1 value
If (iUBound - iLBound) Then
'Move the largest value to the rightmost position, otherwise
'we need to check that iLeftCur does not exceed the bounds of the
'array on EVERY pass (time consuming)
iMax = 1
For iOuter = iLBound To iUBound
If lngArray(iOuter) > lngArray(iMax) Then iMax = iOuter
Next iOuter
iTemp = lngArray(iMax)
If Not IsMissing(swapArray) Then iTemp2 = swapArray(iMax)
lngArray(iMax) = lngArray(iUBound)
If Not IsMissing(swapArray) Then swapArray(iMax) = swapArray(iUBound)
lngArray(iUBound) = iTemp
If Not IsMissing(swapArray) Then swapArray(iUBound) = iTemp2
'Start quicksorting
If Not IsMissing(swapArray) Then
InnerQuickSort lngArray, iLBound, iUBound, swapArray
Else
InnerQuickSort lngArray, iLBound, iUBound
End If
End If
End Sub
Private Sub InnerQuickSort(ByRef lngArray() As Variant, ByVal iLeftEnd As Long, ByVal iRightEnd As Long, Optional ByRef swapArray As Variant)
Dim iLeftCur As Long
Dim iRightCur As Long
Dim iPivot As Variant, iPivot2 As Variant
Dim iTemp As Variant, iTemp2 As Variant
If iLeftEnd >= iRightEnd Then Exit Sub
iLeftCur = iLeftEnd
iRightCur = iRightEnd + 1
iPivot = lngArray(iLeftEnd)
If Not IsMissing(swapArray) Then iPivot2 = swapArray(iLeftEnd)
'Arrange values so that < pivot are on the left and > pivot are on the right
Do
'Find >= value on left side
Do
iLeftCur = iLeftCur + 1
Loop While lngArray(iLeftCur) < iPivot
'Find <= value on right side
Do
iRightCur = iRightCur - 1
Loop While lngArray(iRightCur) > iPivot
'No more swapping to do
If iLeftCur >= iRightCur Then Exit Do
'Swap
iTemp = lngArray(iLeftCur)
If Not IsMissing(swapArray) Then iTemp2 = swapArray(iLeftCur)
lngArray(iLeftCur) = lngArray(iRightCur)
If Not IsMissing(swapArray) Then swapArray(iLeftCur) = swapArray(iRightCur)
lngArray(iRightCur) = iTemp
If Not IsMissing(swapArray) Then swapArray(iRightCur) = iTemp2
Loop
'Call quicksort recursively on left and right subarrays
lngArray(iLeftEnd) = lngArray(iRightCur)
If Not IsMissing(swapArray) Then swapArray(iLeftEnd) = swapArray(iRightCur)
lngArray(iRightCur) = iPivot
If Not IsMissing(swapArray) Then swapArray(iRightCur) = iPivot2
If Not IsMissing(swapArray) Then
InnerQuickSort lngArray, iLeftEnd, iRightCur - 1, swapArray
InnerQuickSort lngArray, iRightCur + 1, iRightEnd, swapArray
Else
InnerQuickSort lngArray, iLeftEnd, iRightCur - 1
InnerQuickSort lngArray, iRightCur + 1, iRightEnd
End If
End Sub
Display More
Re: Find Method from userform, run-time error 91 when find returns nothing
Hi castc468,
Glad to hear it works, It was my pleasure! Keep coding there's always something new to learn, no matter how long you've been at it.
Good luck and have a great day,
MJ
Re: MS XLS function to calculate centroid of a polygon
Hi rcpomp,
I wasn't sure if you wanted his to be a function or a subroutine. As the code stands you would have to check the codename of the sheet that contains the data, you can find this in the vba editor, under project explorer in your workbook > excel objects. It should be sheet1 or sheet2 etc... Then in my code where it says:
you would change Sheet1 to whatever your sheet codename is. Or you can have the code obtain a reference to the worksheet by its name by replacing that line with:
Quote
- in a cell to the right, entered "=centroid ( " and gave as parameters the cells A2:B5)
- got error message
what am i doing wrong?
A subroutine doesn't run from a function like that, you would need to run the macro either by clicking inside the code in VBA editor and pressing F5 or by going into the Developer Tab and selecting Macros.
I can turn this into a worksheet function if you like but I would need to know what you would like it to return. For example, there can be two functions (one for x-pos and one for y-pos), it can be an array function, it can return return a string that contains the coordinate pair, (x,y).
Cheers,
MJ
Re: Find Method from userform, run-time error 91 when find returns nothing
Hi castc468,
Try this:
Private Sub NumberTextBox_AfterUpdate()
Dim Found As Range
Set Found = Sheets("Index").Columns(1).Find(What:=NumberTextBox.Value, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=True, SearchFormat:=False)
If Not Found Is Nothing Then
OKOnly = MsgBox("This # is already in use! Please enter another #", vbOKOnly + vbExclamation, "Error")
Else
NameTextBox.SetFocus
End If
End Sub
Cheers,
MJ
EDIT: Sorry, just realized it should probably not warn you when the field is blank... change this line:
To this one:
Re: MS XLS function to calculate centroid of a polygon
Hi rcpomp,
Paste the following code into a module.
Make sure to change which sheet oWS refers to, it should point to a sheet with (x,y) coordinates positioned in column A and B something like this:
[TABLE="class: grid"]
x
[/td]y
[/td]1
[/td]-1
[/td]2
[/td]-14
[/td]10
[/td]-10
[/td]
[/TABLE]
It will put the centroid position to the right of the data. If you have any questions feel free to ask.
Cheers,
MJ
Sub Centroid()
Dim oWS As Worksheet
Dim vCoords As Variant
Dim vRow() As Variant
Dim i As Long
Dim Area As Double
Dim xPos As Double, yPos As Double
Set oWS = Sheet1 'This should be the sheet where the (x,y) coords are stored in column 1 and 2 respectively with headers.
vCoords = oWS.Range(oWS.Cells(2, 1), oWS.Cells(2, 1).End(xlDown).End(xlToRight)).Value
ReDim vRow(LBound(vCoords, 2) To UBound(vCoords, 2))
For i = LBound(vCoords, 2) To UBound(vCoords, 2)
vRow(i) = vCoords(1, i)
Next i
vCoords = AddRow(vCoords, vRow)
Area = CalcArea(vCoords)
xPos = CalcxPos(vCoords, Area)
yPos = CalcyPos(vCoords, Area)
oWS.Cells(1, 5) = "x"
oWS.Cells(1, 6) = "y"
oWS.Cells(2, 4) = "Centroid:"
oWS.Cells(2, 5) = xPos
oWS.Cells(2, 6) = yPos
End Sub
Private Function CalcxPos(vCoords As Variant, Area As Double) As Double
Dim i As Long
For i = 1 To UBound(vCoords, 1) - 1
CalcxPos = CalcxPos + (vCoords(i, 1) + vCoords(i + 1, 1)) * (vCoords(i, 1) * vCoords(i + 1, 2) - vCoords(i + 1, 1) * vCoords(i, 2))
Next i
CalcxPos = CalcxPos / (6 * Area)
End Function
Private Function CalcyPos(vCoords As Variant, Area As Double) As Double
Dim i As Long
For i = 1 To UBound(vCoords, 1) - 1
CalcyPos = CalcyPos + (vCoords(i, 2) + vCoords(i + 1, 2)) * (vCoords(i, 1) * vCoords(i + 1, 2) - vCoords(i + 1, 1) * vCoords(i, 2))
Next i
CalcyPos = CalcyPos / (6 * Area)
End Function
Private Function CalcArea(vCoords As Variant) As Double
Dim i As Long
For i = 1 To UBound(vCoords, 1) - 1
CalcArea = CalcArea + vCoords(i, 1) * vCoords(i + 1, 2) - vCoords(i + 1, 1) * vCoords(i, 2)
Next i
CalcArea = 0.5 * CalcArea
End Function
Private Function AddRow(InputArr As Variant, vRow As Variant) As Variant
Dim vTemp As Variant
Dim i As Long
If LBound(vRow) <> LBound(InputArr, 2) Or UBound(vRow) <> UBound(InputArr, 2) Then AddRow = 0: Exit Function
vTemp = TransposeArray(InputArr)
ReDim Preserve vTemp(LBound(vTemp, 1) To UBound(vTemp, 1), LBound(vTemp, 2) To UBound(vTemp, 2) + 1)
vTemp = TransposeArray(vTemp)
For i = LBound(vTemp, 2) To UBound(vTemp, 2)
vTemp(UBound(vTemp, 1), i) = vRow(i)
Next i
AddRow = vTemp
End Function
Private Function TransposeArray(InputArr As Variant) As Variant
Dim RowNdx As Long
Dim ColNdx As Long
Dim LB1 As Long
Dim LB2 As Long
Dim UB1 As Long
Dim UB2 As Long
Dim OutputArr() As Variant
LB1 = LBound(InputArr, 1)
LB2 = LBound(InputArr, 2)
UB1 = UBound(InputArr, 1)
UB2 = UBound(InputArr, 2)
ReDim OutputArr(LB2 To LB2 + UB2 - LB2, LB1 To LB1 + UB1 - LB1)
For RowNdx = LB2 To UB2
For ColNdx = LB1 To UB1
OutputArr(RowNdx, ColNdx) = InputArr(ColNdx, RowNdx)
Next ColNdx
Next RowNdx
TransposeArray = OutputArr
End Function
Display More
Re: Dynamically fill array with range(a12:a27) use each item in array as part of file
Hi gerneka,
The following code should so as you asked.
Cheers,
MJ
Sub ClearBooks()
Dim oWB As Workbook
Dim oWS As Worksheet
Dim vBooks As Variant
Dim sFilePath As String
Dim i As Integer
sFilePath = "FilePath"
vBooks = Sheet1.Range("A12:A27").Value
Append2D vBooks, ".xls"
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error GoTo errH:
For i = LBound(vBooks, 1) To UBound(vBooks, 1)
Set oWB = Workbooks.Open(sFilePath & vBooks(i, 1))
Set oWS = oWB.Sheets(1)
oWS.Range("A2:H21").ClearContents
oWS.Range("K4:P5").ClearContents
oWB.Close SaveChanges:=True
Next
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Exit Sub
errH:
Application.ScreenUpdating = True
Application.DisplayAlerts = True
MsgBox Err.Description
End Sub
Private Sub Append2D(ByRef InputArr As Variant, sAppend As String)
Dim i As Long, j As Long
Dim vTemp() As Variant
ReDim vTemp(LBound(InputArr, 1) To UBound(InputArr, 1), LBound(InputArr, 2) To UBound(InputArr, 2))
For i = LBound(InputArr, 1) To UBound(InputArr, 1)
For j = LBound(InputArr, 2) To UBound(InputArr, 2)
vTemp(i, j) = InputArr(i, j) & sAppend
Next j
Next i
InputArr = vTemp
End Sub
Display More