Columns to multiple rows [duplicate] - vba

This question already has answers here:
Transpose multiple columns to multiple rows with VBA
(4 answers)
Closed 6 years ago.
I would like a macro to convert the following
NAME COLOR1 COLOR2 COLOR3 COLOR4
jane blue pink red teal
john red black green gold
to
NAME COLOR
jane blue
jane pink
jane red
jane teal
john red
john black
john green
john gold
I have tried using the built-in transpose tool, but that does not seem to work. It seems like I need a custom script...

With data in rows 2 and 3, pick a cell and enter:
=INDEX($A$2:$A$9999,ROUNDUP(ROWS($1:1)/4,0))
Next to it enter:
=OFFSET($B$2,ROUNDUP(ROWS($1:1)/4,0)-1,MOD(ROWS($1:1)-1,4))
and copy these down:
If you really love macros, have the macro deposit and copy the formulas.

Related

SQL where NOT EQUAL TO isn't working as intended - SQL Server 2016

I have the following query that is working differently when using != (or <>) compared to =.
The example I'm trying this with works as follows.
SELECT COUNT(*) FROM table1
returns 100.
SELECT COUNT(*)
FROM table1
WHERE year = '2017/2018' AND SOURCE = 'CSV'
returns 30.
Why then would the below not return a count of 70?
SELECT COUNT(*)
FROM table1
WHERE year != '2017/2018' AND SOURCE != 'CSV'
It appears to treat it like an OR instead of AND when updating to != and I'm struggling to figure out why. I have got around the issue by changing my query to use NOT EXISTS with a subselect, but the initial question remains.
Because there are rows where year is 2017/18 but source is not CSV, or source is CSV but year is not 2017/18. See De Morgan's laws.
Perhaps what you want is:
WHERE NOT (year = '2017/2018' AND SOURCE = 'CSV')
Personally I'm not normally a big fan of the NOT () wrapper, but in this case it best describes the semantics you're after. You could also say:
WHERE year <> '2017/2018' OR SOURCE <> 'CSV'
---- important difference ^^
Example db<>fiddle
Think about it another way. The parking lot has 10 cars, and we want to find out how many cars are red BMWs (let's call it x), and how many cars are NOT red BMWs (which should be 10 - x):
Color
Make
Red?
BMW?
Red ANDBMW?
NotRed?
NotBMW?
Not Red ANDNot BMW?
Not Red ORNot BMW?
Red
BMW
Yes
Yes
Yes
No
No
No
No
Red
BMW
Yes
Yes
Yes
No
No
No
No
Red
BMW
Yes
Yes
Yes
No
No
No
No
Silver
BMW
No
Yes
No
Yes
No
No
Yes
Red
Honda
Yes
No
No
No
Yes
No
Yes
Purple
Toyota
No
No
No
Yes
Yes
Yes
Yes
Green
Lexus
No
No
No
Yes
Yes
Yes
Yes
Green
Toyota
No
No
No
Yes
Yes
Yes
Yes
Black
Ford
No
No
No
Yes
Yes
Yes
Yes
Orange
Audi
No
No
No
Yes
Yes
Yes
Yes
Sum of Yes:
4
4
3
6
6
5
7
If you count up all the cars that are both red and BMW, you get 3. If you want the inverse of that (the 7 remaining cars), you can't count up all the cars that are both NOT red and NOT BMW. This would skip the silver BMW and the red Honda, giving 5, not 7. You need to count all the cars that are either not red OR not BMW. Or that are NOT both red AND BMW.

How do you “pivot” using conditions, aggregation, and concatenation in Pandas?

I have a dataframe in a format such as the following:
Index Name Fruit Quantity
0 John Apple Red 10
1 John Apple Green 5
2 John Orange Cali 12
3 Jane Apple Red 10
4 Jane Apple Green 5
5 Jane Orange Cali 18
6 Jane Orange Spain 2
I need to turn it into a dataframe such as this:
Index Name All Fruits Apples Total Oranges Total
0 John Apple Red, Apple Green, Orange Cali 15 12
1 Jane Apple Red, Apple Green, Orange Cali, Orange Spain 15 20
Question is how do I do this? I have looked at the groupby docs as well as a number of posts on pivot and aggregation but translating that into this use case somehow escapes me. Any help or pointers much appreciated.
Cheers!
Use GroupBy.agg with join, create column F by split and pass to DataFrame.pivot_table, last join together by DataFrame.join:
df1 = df.groupby('Name', sort=False)['Fruit'].agg(', '.join)
df2 = (df.assign(F = df['Fruit'].str.split().str[0])
.pivot_table(index='Name',
columns='F',
values='Quantity',
aggfunc='sum')
.add_suffix(' Total'))
df3 = df1.to_frame('All Fruits').join(df2).reset_index()
print (df3)
Name All Fruits Apple Total \
0 John Apple Red, Apple Green, Orange Cali 15
1 Jane Apple Red, Apple Green, Orange Cali, Orange Spain 15
Orange Total
0 12
1 20

SQL query to select records based on existence of required or lack of excluded values

I'm hoping for some assistance in building a simple query that will return a list of names from a given table where an entry containing a required color exists and no entry containing an excluded color exists.
id name color
--- -------- --------
1 james red
2 james blue
3 james green
4 jim red
5 jim purple
6 bob white
7 bob red
8 bob pink
9 charlie white
10 charlie green
11 charlie black
12 kate violet
13 kate pink
14 kate red
I want to select all names where:
there must be a 'red' entry, i.e. excluding charlie
there must not be a 'pink' entry, i.e. excluding kate and bob
i.e.
james - included, has red, does not have pink
jim - included, has red, does not have pink
bob - excluded, has red but also has pink, which is excluded
charlie - excluded, does not have red
kate - excluded, has red, but also has pink, which is excluded
Ideally the output would include the list of distinct names (i.e. james, jim) and the query would allow me to use lists of colors for the required or excluded colors.
Thanks for your help!
You can use aggregation:
select name
from t
where color in ('pink', 'red')
group by name
having min(color) = 'red' and min(color) = max(color);
This version just limits the colors to 'pink' and 'red'. The having clause checks that only one color is present for a name, and that that color is 'red'.
Yes, you can use the IN and NOT IN operator in the WHERE clause. Example:
SELECT *
FROM table
WHERE column_1 IN ('red')
AND column_1 NOT IN ('pink')
If the list of inclusions and exclusions are static then you can use the query above.
If the list is dynamic, such as a table that stores the inclusion and exclusion lists, then you can replace the static values with a SELECT statement.

Find a list of words in an excel sheet

I am trying to find a list of words and if the word(s) exist then a count of each word) in an excel sheet which has multiple columns. For example:
Words to find
Apple
Banana
Kale
Chard
Excel sheet columns
ID Name Feedback_1 Feedback_2
121 John I don't like Bananas Bananas
122 Adam Kale is good Apple
123 Rob Chard sucks Kale
Output
Apple 1
Banana 2
Kale 2
Chard 1
Try
{=SUMPRODUCT(--(IFERROR(FIND(G1,Rng_Feed),0)>0))}
where Rng_Feed is a continuous range of Feedback_1 and Feedback_2. You can use $C$2:$D$5 if you do not want to name this range nor use it in the formula.

Excel VBA - Group Data by Column A, Get the Range Value from C - Copy results to New Sheet

I've been trying to search for an example of this grouping and tested few code snippets but haven't been able to adapt it to what I need as I'm just getting to know Excel vba.
What I'm trying to do is to group by column A then get the range of the values used in that category which are in column C and get the results in a new worksheet.
Main Sheet.
A B C D
3 Baseball 4 Blue
2 Football 1 Red
2 Football 3 Red
3 Baseball 4 Blue
1 Soccer 2 Green
3 Baseball 4 Blue
1 Soccer 3 Green
1 Soccer 5 Green
2 Football 2 Red
Expected Results:
New Sheet.
A B C D
1 Soccer 2-5 Green
2 Football 1-3 Red
3 Baseball 4 Blue
If you need column C to be a range of value, eg 2 - 5, then it's text in Excel. Pivot table only able to return Min, Max, Sum, Average, but not range of the value.
You will need using VBA to solve the problem.
First, copy column A,B,D to some where, then using Remove Duplicate.
To find out the Unique combination.
Eg: (Assuming you have some new records in future)
A B C D
3 Baseball 4 Blue
2 Football 1 Red
2 Football 3 Red
3 Baseball 4 Blue
1 Soccer 2 Green
3 Baseball 4 Blue
1 Soccer 3 Green
1 Soccer 5 Green
2 Football 2 Red
4 Tennis 3 Yellow
Then you should have something like below:
A B D
1 Soccer Green
2 Football Red
3 Baseball Blue
4 Tennis Yellow
Then using Loop, to find out the range of the value for each of the Unique Combination (here we have 4 unique records).
*** assume that you know how to use loop to find out the Range of each combination.
I've actually figure this out:
For Each key In fCatId.Keys
'Debug.Print fCatId(key), key
With wshcore
llastrow = wshcore.Range("A" & Rows.Count).End(xlUp).Row
.Range("A1:N" & llastrow).AutoFilter
.Range("A1:N" & llastrow).AutoFilter Field:=1, Criteria1:=fCatId(key)
lwmin = WorksheetFunction.Subtotal(5, Range("H:H"))
lwmax = WorksheetFunction.Subtotal(4, Range("H:H"))
Im getting column a: fcatid, b: key, lwmin: lowest value and lwmax: highest.