Excel dynamic data series. Unusual data look and chart - excel

Since I solved previous problem with collecting data from database, I need to put that data on a chart now. I am working on a report generating software called ReportWorx.
Problem is, data comes in series and looks like this:
ID DATE SAMPLE
1 XX-XX-XX VALUE
1 XX-XX-XX VALUE
1 XX-XX-XX VALUE
2 XX-XX-XX VALUE
2 XX-XX-XX VALUE
3 XX-XX-XX VALUE
3 XX-XX-XX VALUE
I can not change how it looks because it is generated automatically. What I want is linear chart in which 1, 2, 3 are series name and of course next to it DATE and VALUE are put on a linear chart (or bargraph, w/e) (Date at X axis, Value at Y axis).
I can`t specify how many records will be there (how many rows) but I found few solutions about creating dynamically increasing charts, so probably it will not be a poblem. I just do not know how to separate thos ID series from each other.
EDIT:
I have found a solution in VBA according to the first answer. Here you have VBA code below:
Sub Rewrite()
Dim row, id
For row = 38 To 1000
For id = 1 To 37
If Sheet1.Cells(row, 1).Value = id Then
Sheet2.Cells(row, 1).Value = Sheet1.Cells(row, 2)
Sheet2.Cells(row, id + 1).Value = Sheet1.Cells(row, 3)
End If
Next id
Next row
End Sub
Thank You #sancho.s

I will post a solution that I use a lot for cases like yours.
With reference to the figure (where I used sample numbers), you set up 3 new columns (D:F here), the header of which contain the corresponding labels. Then you use a formula for "splitting" the list of X data (column B here) associated with each label, and assigning a "NULL" value for data not corresponding (#N/A here, but you can choose whatever you want):
=IF($A3=D$2,$B3,$B$1)
You enter this in D3. The absolute/relative indexing used allows for copy-and-paste throughout D3:F9.
Cell B1 here contains the "NULL" value.
Then you plot 3 series: column C against columns D, E, F.
PS: I guess you could split the Y data column instead, with similar results. For some reason that I do not recall, I decided a long time ago that this was the best option, at least in my case then. You may want to try out the other option.
PS2: This also works for data that is not sorted by label.
PS3: Using NA() as the "NULL" value avoids cell values being taken as zero and then showing up in the chart, as it is the case with other errors (e.g., try using =1/0 in B1). It is the best option I found so far. Alternatively (just in case you find it useful), you can use an explicit value which is outside the actual X data range, but then you would have to manually set the X axis range. All this is for a Scatter plot, just check what works for your case.

Related

Making a vector out of excel columns using python

everyone...
I just started on python a couple of days ago because I require to handle some excel data in order to automatically update the data of certain cells from one file into another.
However, I'm kind of stuck since I have barely programmed before, and it's my first time using python as well, but my job required me to find a solution and I'm trying to make it work even though it's not my field of expertise.
I used the "xlrd library", imported my file and managed to print the columns I'm needing... However, I can't find a way to put those columns into a matrix in order to handle the data like this:
Matrix =[DataColumnA DataColumnG DataColumnH] in the size [nrows x 3]
As for now, I have 3 different outputs for the 3 different columns I need, but I'm trying to join them together into one big matrix.
So far my code looks like this:
import xlrd
workbook = xlrd.open_workbook("190219_serviciosWRAmanualV5.xls");
worksheet = workbook.sheet_by_name("ServiciosDWDM");
workbook2 = xlrd.open_workbook("Potencia2.xlsx");
worksheet2 = workbook2.sheet_by_name("Hoja1");
filas = worksheet.nrows
filas2 = worksheet2.nrows
columnas = worksheet.ncols
for row in range (2, filas):
Equipo_A = worksheet.cell(row,12).value
Client_A = worksheet.cell(row,13).value
Line_A = worksheet.cell(row, 14).value
print (Equipo_A, Line_A, Client_A)
So I have only gotten, as mentioned above, the data in the columns which is what I'm printing which you can see.
What I'm trying to do, or the main thing I need to do is to read the cell of the first row in Column A and look for it in the other excel file... if the names match, I would have to validate that for the same row (in file 1) the data in both the ColumnG and ColumnH is the same as the data in the second file.
If they match I would have to update Column J in the first file with the data from the second file.
My other approach is to retrieve the value of the cell in ColumnA and look for it in the column A of the second file, then I would make an if conditional to see if ColumnsG and H are equal to Column C of 2nd file and so on...
The thing here is, I have no idea how to pin point the position of the cell and extract the data to make the conditional for this second approach.
I'm not sure if by making that matrix my approach is okay or if the second way is better, so any suggestion would be absolutely appreciated.
Thank you in advance!

Excel VBA - Change cell value via another cell?

So VBA is completely new to me. I come from a C# background.
Currently creating an order form, whereby I can input the total amount I require of an object and then the price is calculated in a different cell.
However I also want the price to change based off amount thresholds for that object.
Say for example 0 - 100 will cost £2.50 so I expect the answer to be anywhere within that range is multiplied by 2.50. Meanwhile if the amount exceeds 100 and becomes 120 I want the object price to now reflect £2.30 and proceed to multiple the 120 by £2.30.
I've noticed a few tutorials on line but they don't exactly explain how I might be able to achieve the above. Wondering if anyone can point me in the right direction?
Non VBA Soluion
If you build a table with the bottom and upper thresholds for a price, you can simply use a VLOOKUP and return the approximate match.
In photo, Column C is the output from the equation that is shown in Column D
VBA Solution
You can also use a simple UDF. Paste the code inside a Module and then you can call the function PRICEINDX from a cell just like any other equation. You can either manually type in a value like PRICEINDX(164) or select a cell that has the value to be tested like PRICEINDX(A1)
You can also set up more complex thresholds easily by using Select Case
Option Explicit
Public Function PRICEINDX(Target As Double) As Double
Dim ans As Double
Select Case Target
Case 0 To 100
ans = 2.5
Case 101 To 200
ans = 2.3
Case 201 To 300
ans = 2.1
Case Is > 300
ans = 2
End Select
PRICEINDX = ans
End Function

Excel - max between 2 series

I have 2 series of data. For sake of simplicity, lets say the data looks like below,
set 1:
1 3
2 3.5
3 4
4 4.5
5 5
6 5.5
7 6
8 6.5
9 7
10 7.5
set 2:
1.5 2
2.8 4.5
3.5 8
4.5 6
5.5 4.8
6.5 4
7.5 6.5
8.5 9
9.5 3
10.5 4
After charting these 2 sets, I want to get the line with the higher data. I want the black line, In the attached pic. How do I get that? My actual data has thousands of data points, so doing this manually isn't possible.
Added later: Another thing I forgot to mention, in my actual data 1 set has about 500 x,y values, and the other set has about 50 values. Though the end points have same/similar x values.
Thanks for your help.
Given your information about the chart and the tables, I would do something like this:
The new series will be based on two formulas:
In Column H, I have the formula for the max value (between your two series):
=MAX(B2,E2)
In Column G, I have the formula that based on the Max value (formula above), which X value I should use (X-value from Series 1 or 2).
=IF(H2=B2,A2,D2)
Then I can plot my graph:
Series 1, Column B
Series 2, Column E
Series 3, Column H.
All series uses the X values of Column G.
Introduction
A few assumptions/comments/pitfalls/constraints regarding my solution:
Set 1 and Set 2 are in columns A till D.
The combined data set will combine the x-values of both Sets, and will have additional data points where the lines cross.
It involves several helper columns, in particular to allow you to copy/paste this across multiple worksheet with data.
I did not try to condense too much, to improve readability, and probably some helper columns could be combined.
It was tested with the data set from the question, but difficult to guarantee all "boundary" conditions, e.g. identical data points between Set 1 and Set 2, zero overlap between the two data sets, empty data sets, etc. (I did test some of these, see my comments at the end).
Set 1 and Set 2 must be sorted (on x-values). If this is not the case, a few additional helper columns are needed to sort the data dynamically.
To better understand the solution described below, see herewith the resulting graph, based on the data set in the question (although I added one data point [2.5;3.75] to avoid having the data points of Set 1 and Set 2 perfectly alternating):
General solution outline / methodology
Combine both datasets in a single (sorted) column;
For all x-values, determine highest y-value, between the y-value in the Set, and the calculated y-value on the line segment from the neighboring values in the other Set (looks simple, in particular with the given example data set, but this is quite tricky to do when data sets have no alternating x-values);
Find the points (x & y values) where the lines of the graph are crossing (intersecting), let's call this Set 3
Combine and sort (on x-values) the three data sets in a two columns (for x & y values).
The details and formulas
For the formulas, I assume row 1 contains headings, and the data start on row 2. All formulas should be entered in row 2, except for a few, where I mention to put them in row 3 (because they need data from the preceding row). The result is in columns E (x-values) and F (y-values), and G till AG are helper columns).
Column E : =INDEX(AH$2:AH$30;MATCH(ROWS(AH$2:AH2);$AJ$2:$AJ$30;0)) These is the actual result. Gets all x-values in AH and sorts these based on an index column AJ; this should actually be the last column in the logical flow, but for presentation purposes it is cleaner to have this next to the input data sets;
F : =INDEX(AF$2:AF$30;MATCH(ROWS(AF$2:AF2);$AG$2:$AG$30;0)) Same for y-values;
G : =IF(ISNA(H2);NA();COUNTIF($H$2:$H$30;"<="&H2)) Creates index to sort combined x-values of both data sets. You also can dynamically sort without such helper column, but then you need a VLOOKUP or INDEX/MATCH and with long decimal numbers I have some bad experiences with these;
H : =IF(ROW()-1<=COUNT($A$2:$A$30);A2;IF((ROW()-1)<=(COUNT($A$2:$A$30)+COUNT($C$2:$C$30));INDEX($C$2:$C$30;ROW()-COUNT($A$2:$A$30)-1;1);NA())) Combines x-values of both data sets, i.e. in columns A & C;
I : =IF(ROW()-1<=COUNT($B$2:$B$30);B2;IF((ROW()-1)<=(COUNT($B$2:$B$30)+COUNT($D$2:$D$30));INDEX($D$2:$D$30;ROW()-COUNT($B$2:$B$30)-1;1);NA())) Same for the y-values;
J : =IF(ROW()-1<=COUNT($A$2:$A$30);"S1";IF((ROW()-1)<=(COUNT($A$2:$A$30)+COUNT($C$2:$C$30));"S2";NA())) Assign "S1", or "S2" to each data point, as indication from which data set they come;
K : =IF(J2=J3;INTERCEPT(I2:I3;H2:H3);NA()) Determines the intercept of the line segment starting at that data point;
L : =IF(J2=J3;SLOPE(I2:I3;H2:H3);NA()) Same for slope;
M : =INDEX(H$2:H$30;MATCH(ROWS(H$2:H2);$G$2:$G$30;0)) Sorts all x-values;
N : =INDEX(I$2:I$30;MATCH(ROWS(I$2:I2);$G$2:$G$30;0)) Same for y-values
O : =INDEX(J$2:J$30;MATCH(ROWS(J$2:J2);$G$2:$G$30;0)) Same for corresponding "S1/S2" value to indicate from which data set they come;
P : =INDEX(K$2:K$30;MATCH(ROWS(K$2:K2);$G$2:$G$30;0)) Same for intercept;
Q : =INDEX(L$2:L$30;MATCH(ROWS(L$2:L2);$G$2:$G$30;0)) Same for slope;
R : =IF(O2="S1";"S2";"S1") Inversion between S1 & S2.
S : {=IFERROR(INDEX($O$2:$Q2;MAX(IF($O$2:$O2=$R3;ROW($O$2:$O2)-ROW(INDEX($O$2:$O2;1;1))+1));2);NA())} Array formula to be put in cell S3 (hence ctrl+shift+enter) that will search for the intercept of the preceding data point of the other data set.
T : {=IFERROR(INDEX($O$2:$Q2;MAX(IF($O$2:$O2=$R3;ROW($O$2:$O2)-ROW(INDEX($O$2:$O2;1;1))+1));3);NA())} Same for slope;
U : =IF(OR(ISNA(N2);NOT(ISNUMBER(S2)));NA();M2*T2+S2) Calculates the y-value on the line segment of the other data set;
V : =MAX(IFNA(U2;N2);N2) Maximum value between the original y-value and the calculated y-value on the corresponding line segment of the other data set;
W : =(V2=N2) Checks whether the y-value comes from the original data set or not;
X : =IF(O2="S1";IF(W2;"S1";"S2");IF(W2;"S2";"S1")) Determines on which data set (line) the y-value sits (S1 or S2);
Y : =IFERROR(AND((X2<>X3);COUNTIF(X3:$X$30;X2)>0);FALSE) Determines when the data sets cross (i.e. the lines on the graph intersect);
Z : =IF(Y2;(S2-P2)/(Q2-T2);NA()) Calculates x-value of intersection;
AA : =IF(Y2;Z2*Q2+P2;NA()) Calculates y-value of intersection;
AB : =COUNTIF($Z$2:$Z$30;"<="&Z2) Index to sort the newly calculated intersection points (I sort them because then the combining with the other data sets is straightforward, re-using formula of column H;
AC : =INDEX(Z$2:Z$30;MATCH(ROWS(Z$2:Z2);$AB$2:$AB$30;0)) Sorted x-values of intersection points;
AD : =INDEX(AA$2:AA$30;MATCH(ROWS(AA$2:AA2);$AB$2:$AB$30;0)) Same for y-values;
AE : =IF(ROW()-1<=COUNT(M$2:M$30);M2;IF((ROW()-1)<=(COUNT(M$2:M$30)+COUNT(AC$2:AC$30));INDEX(AC$2:AC$30;ROW()-COUNT(M$2:M$30)-1;1);NA())) Combine x-values of Set 1, Set 2, and the intersection points;
AF : =IF(ROW()-1<=COUNT(V$2:V$30);V2;IF((ROW()-1)<=(COUNT(V$2:V$30)+COUNT(AD$2:AD$30));INDEX(AD$2:AD$30;ROW()-COUNT(V$2:V$30)-1;1);NA())) Same for y-values;
AG : =IF(ISNA(AE2);NA();COUNTIF($AE$2:$AE$30;"<="&AE2)) Create index to sort the resulting data set (and this is used to calculate the final results in columns E & F;
All formulas go until row 30, but this need to be changed of course based on the actual data sets. The idea is to add these formulas to one worksheet, and then columns E > AG can be copied to all other worksheets. There are obviously quite a few #NA values, but this is on purpose, and are not errors or mistakes. On request, I can share the actual spreadsheet, so you do not have to retype all formulas.
Some additional comments
You have to modify some formulas (the sort indices) if there are identical x-values, either within Set 1 (which I will not cover here, as it seems this would be unlikely, or be data input errors), or between Set 1 and Set 2. The dynamic sorting does not work in that case. A workaround is to create a "synthetic" sort column, e.g. with =TEXT(J2;"0000.00000000000")&L2. This formats all numbers the same way as text, and appends S1 or S2. So this should give unique sort values, which would sort the same way as the corresponding numbers.
Empty data sets or data sets with only 1 value are not treated correctly either (the intercept formulas and finding values for the "previous" data point are meaningless in these cases).

(Excel 2013/Non-VBA) Format Data column based on value of another cell?

We have a column that is query driven, and the query partially formats the values in the column using math based off the value of a "user entry cell" on another sheet.
For the really curious, our query looks like this:
DECLARE #rotationsNum INT
SET #rotationsNum = ?
SELECT t.Piece_ID, t.Linear_Location, ((ROW_NUMBER() OVER(ORDER BY
Linear_Location) -1 )%#rotationsNum )*(360/#rotationsNum) AS Rotation FROM
(SELECT Position.Feature_Key, Piece_ID, ((Place-1)%(Places/#rotationsNum))+1 AS Linear_Location, Place, Measured_Value, Places FROM Fake.dbo.Position LEFT JOIN Fake.dbo.Features
ON Position.Feature_Key = Features.Feature_Key WHERE Position.Inspection_Key_FK = (SELECT Inspection_Key FROM Fake.dbo.Inspection WHERE Op_Key = ?)) AS t
ORDER BY Piece_ID, Linear_Location
The first parameter "#rotationsNum" is a cell that will always have a value between 1-4. IF the value is 1, the entire column will show "0"s, which we want to show as "N/A". However, it isn't as simple as "How to hide zero data.." Because if the "#rotationsNum" == 2, 3, or 4, there will still be 0 values in the column that need to be shown.
A "#rotationsNum" value of 2 will have the query write the column as such: example
So I am trying to come up with a way to format the column =IF(cell>1, do nothing, overwrite entire column to say "NA"). But I don't think it is that straight forward since the column is query driven.
My resolution was to format the column so that if the cell that drives the "#rotationsNum" parameter is below 2, then the whole column just gets "grayed out". It kind of makes it look like a redaction, and isn't as desirable as "NA", but it works for our purposes. Hopefully this solution helps someone else who stumbles upon this problem.

Using tbl.Lookup to match just part of a column value

This question relates to the Schematiq add-in for Microsoft Excel.
Using =tbl.Lookup(table, columnsToSearch, valuesToFind, resultColumn, [defaultValue]) the values in the valuesToFind column have a consistent 3 characters to the left and then varying characters after (e.g. 908-123456 or 908-321654 - i.e. 908 is always consistent)
How can I tell the function to lookup the value based on the first 3 characters only? The expected answer should be the sum of the results of the above, i.e. 500 + 300 = 800
tbl.Lookup() works by looking for an exact match - this helps ensure it's fast but in this case it means you need an extra step to calculate a column of lookup values, something like this:
A2: =tbl.CalculateColumn(A1, "code", "x => LEFT(x, 3)", "startOfCode")
This will give you a new column that you can use for the columnsToSearch argument, however tbl.Lookup() also looks for just one match - it doesn't know how to combine values together if there is more than one matching row in the table, so I think you also need one more step to group your table by the first 3 chars of the code, like this:
A3: =tbl.Group(A2, "startOfCode", "amount")
Because tbl.Group() adds values together by default, this will give you a table with a row for each distinct value of startOfCode and the subtotal of amount for each of those values. Finally, you can do the lookup exactly as you requested, which for your input table will return 800:
A4: =tbl.Lookup(A3, "startOfCode", "908", "amount")

Resources