Faster Way of Grouping Rows using Loops in VBA - excel

For k = 1 To 25000
z = Sheet6.Range("E4").Offset(k, 0)
If (z = 3 Or z = 4) Then
Range("E4").Offset(k, 0).Rows.Group
Else
End If
Next k
I am trying to create a loop for grouping with a condition. If the given cell (E5, E6 and so on) value is 3 or 4 then these rows will be grouped together as in Excel function "Data > Outline > Group". And this loop will run for 25000 lines, sometimes more. With my code and 25000 lines, this task takes approx. 20 minutes to run which is not ok. How can I fasten up this process? I would normally create an array to run the loop quicker but when it's "grouping" I couldn't come up with how. Bear in mind that I am using some speed-up techniques such as application calculation manual, no screen updating, no enable events. I am posting the link of an image for the end result to better explain what I need

Related

Loop to select rows until I reach a target number

I have two dataframes, which I join to see the active people. There are people who stop being active and I use one of the dataframes to fill the other one.
mass pnr freq
1 [40666303, 68229102, 35784905, 47603805] 4
54 [17182402] 1
234 [07694901, 35070201, 36765601] 3
The other table looks the same I just need to select enough people to reach my target of 7500-7600 people (40666303 - this is one person and 'freq' is the number of people in the list. It doesn't matter what is the 'mass', I just need when the sum of 'freq' is between 7500 and 7600 the process to stop. Now I need 400 people, but next month it is possible to need 20 people, it differs every month. Basically, my code now removes the non-active people and when it removes them i need to replace them with active. The first run of the process I used this code to select the initial 7500 people:
target = 7500
freq_sum = sum(mass_grouped3['freq'])
new_mass_not_in_whitelist1['records_to_select'] = [math.ceil(int((el * target ) / freq_sum )) for el in new_mass_not_in_whitelist1['freq']]
But now, with this code I am not getting the desired sum of people to fill the missing gap of 400 people. Also, it would be good to not select only the first rows, but maybe every other or some random condition. What can I change to work the way I explained?

Fastest way to insert multiple page breaks in Excel with VBA

I need to insert multiple page breaks into a document (a few hundred) and am trying to find the fastest way. I know with most sheet operations in excel it is fastest to batch them as an array or range and then perform them all at once. But with page breaks I can't see a way around performing individually within a loop.
The code below works but is slow
With shtBagCheckList
.Cells.PageBreak = xlPageBreakNone
For i = 13 To lngArrayRows Step 12
.Cells(i, 1).PageBreak = xlPageBreakManual
Next i
End With
A technique I sometimes use to apply formatting is to combine all the ranges that require the same formatting into one range and then apply the formatting to the combined range. Like this:
Set rngToBold = Union(rngToBold, Rng2) 'etc in a loop
rngToBold.Font.Bold = True
But doing that with page breaks, the break is only applied to the first element in the range. For example doing the below only create a page break at row 12, none at 24
set rng = range("A12", "A24")
rng.PageBreak = xlPageBreakManual
What is the fastest way to add many page breaks into a sheet?
Update
Here are the results I got using tips from user11121185 and Tim Williams.
It turns out using HpageBreaks.add is way faster
1 rng.Page Break, calculation on: 20.594 (45%)
2 rng.Page Break, calculation off: 13.219 (29%)
3 rng.Page Break, calculation off, display breaks off: 11.922 (26%)
4 hbreaks.add,calculation on: 0.018 (0%)
5 hbreaks.add, calculation off : 0.203 (0%)
6 hbreaks.add, calculation off, display page breaks off: 0.312 (1%)
Total Time: 46.267
(calculation off means automatic calculation and screen updating off)
Usage is like this:
sheet.HPageBreaks.Add sheet.range("A10")
Or:
With shtBagCheckList
.Cells.PageBreak = xlPageBreakNone
For i = 13 To lngArrayRows Step 12
.HPageBreaks.Add .Cells(i, 1)
Next i
End With

matlab multidimensional array to excel

I have a Matlab script with an output of a multidimensional array LCOE (3 dimensions) of size 16:12:34. This output needs to be written to Excel, therefore I use xlswrite.
I have tried this:
T = LCOE(:,:,1);
xlswrite('filename', T, 'sheetname', 'B2');
This does what it's supposed to, but only writes one table to excel, and I would like to write all 34 tables to excel underneath each other, spaced by `2 blank rows.
Then, I tried this:
for y = 1:34
T = LCOE(:,:,y)
xlswrite('filename', T, 'sheetname', strcat('B', num2str(2+(y-1)*18)));
This works, but is very slow, since matlab writes each table separately to excel. Is there a faster way to do this?
Instead of using xlswrite again and again. Dump all the values of a 3D matrix into a 2D matrix and add rows of NaNs so that when you write that to excel file, you get 2 blank rows.
Following code improves the execution time by the factor of more than 10.
LCOE = 100*rand(16,12,34); % Taking random values for LCOE
T = NaN(18*34-2 ,12); % 1. Pre-allocation 2. 16+2 = 18
% Following loop dumps all the values of 3D matrix into a 2-D followed by 2 rows of NaN
% to leave 2 blank rows in excel file.
for k = 1:34
T(18*(k-1)+[1:16], :) = LCOE(:,:,k);
end
xlswrite('filename', T, 'sheetname', 'B2'); % Writing the Excel file
In my system, my code takes about 1 second to execute while your code takes about 10.5 seconds. So that's a significant difference.

Loop through a combination of numbers

I am trying to think of a way to loop through a number of combinations making sure that I go through each available combination without repeat. Let me explain. I have a set of numbers, for example
20,000
25,000
27,000
29,000
and I would like to alter this set of numbers via a loop and copy the new numbers into a different sheet so that my formulas on that sheet can calculate whatever I need them to calculate. For example, the first couple of iterations might look something like this:
1st
20,000 x 1.001
25,000 x 1
27,000 x 1
29,000 x 1
2nd
20,002 x 1.001
25,000 x 1.001
27,000 x 1
29,000 x 1
The first row of numbers should never exceed the second. So 20,000 should only go as high as 25,000.
I was able to set up a system whereby I set up a matrix and then loop through a random set of combinations using =rand() however this does not ensure I hit every combination and also repeats combinations.
Can anyone explain the math behind this and also how I would use a loop to accomplish my goal?
Thank you!
Try starting with smaller numbers.
See if this works for you.
Sub looper()
'First Array
Dim myArray(9) As Double
For i = 1 To 10
myArray(i - 1) = i
Next i
'Second Array
Dim myOtherArray(9) As Double
For i = 1 To 10
myOtherArray(i - 1) = i
Next i
'Loop through each one
For Each slot In myArray
For Each otherSlot In myOtherArray
Debug.Print (slot & " * " & otherSlot & " = " & slot * otherSlot)
Next otherSlot
Next slot
End Sub
GD user1813558,
Your question contains too little detail and is too broadly scoped to be able to provide a accurate answer.
Are your numbers arbitrary (i.e. the ones you provided are 'just'
samples) or will they be fixed as per your indicated numbers ?
Will there always be only 4 numbers ?
Is the distribution of your startnumbers (i.e. their difference
value) always as per your indication 0, +5000, +2000, +2000
Will the results of all 'loops' (or iterations) need to be copied to
a different sheet ? (i.e looping from 20.000 to 25.000 by increments
of 1.001 would require about 223 iterations, and subsequently sheets,
before the result starts exceeding 25.000 ?)
Does a new sheet need to be created for each iteration result or are they
existent or will the result be copied to the same sheet for every iteration ?
In short, please provide a more accurate question.

Excel 2003: Better workaround for 10 if statements

I have a very rough workaround for 10 statements using a combination of 2 cells, as follows
Cell 1 (O2)
=IF(C2="TW2-OUT",VLOOKUP($D2,Players,8,FALSE)+VLOOKUP($D2,Players,9,FALSE),IF(C2="TW2-IN",IF($D2="","",VLOOKUP($D2,Players,10,FALSE)),IF(C2="Playing",IF($D2="","",VLOOKUP($D2,Players,8,FALSE)+VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE)),IF(C2="IN1OUT2",VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE),IF(C2="TW1-OUT",IF($D2="","",VLOOKUP($D2,Players,8,FALSE)),IF(C2="TW1-IN",IF($D2="","",VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE)),IF(C2="TW3-OUT",VLOOKUP($D2,Players,8,FALSE)+VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE),0)))))))+P2
Cell 2 (P2)
=IF(C2="TW3-IN",IF($D2="","",VLOOKUP($D2,Players,11,FALSE)),IF(C2="IN2OUT3",VLOOKUP($D2,Players,10,FALSE),IF(C2="IN1OUT3",VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE),0)))
Is there a better way of doing this. I have read via a Google search about using a table approach with an array to achieve the same effect. However, in my case the status of a player determines the score of a player and this complicates things for me. Here are the 10 possible statuses (if statements) broken down as follows with how scored are calculated:
TransferStatuses Cols
Playing 8+9+10+11
TW1-IN 9+10
TW1-OUT 8
TW2-IN 10+11
TW2-OUT 8+9
TW3-IN 11
TW3-OUT 8+9+10
IN1OUT2 9
IN1OUT3 9+10
IN2OUT3 10
8 = ColK (Transfer Window 0)
9 = ColL(Transfer Window 1)
10 = ColM (Transfer Window 2)
11 = ColN(Transfer Window 3)
The 'score' array will be along the lines as follows:
=VLOOKUP(C2,$S$2:$T$11,2,FALSE)
The problem is that I don't know how to put it all together to make it work, i.e. I have to extend my formula to 300 cells but I don't know how to implement it so that the array calculates the scores correctly for each player?
Can someone help?
If I understand you correctly I would approach it like this:
Set up a matrix of binary values that specify, for each status, which columns should be added up. Use OFFSET and MATCH to look up the status for each data row and return the array/range of binary values, and SUMPRODUCT to sum it all up. See screenshot:

Resources