I have multiple lists that are in separate columns in excel. What I need to do is combine these columns of data into one big column. I do not care if there are duplicate entries, however I want it to skip row 1 of each column.
Also what about if ROW1 has headers from January to December, and the length of the columns are different and needs to be combine into one big column?
ROW1| 1 2 3
ROW2| A D G
ROW3| B E H
ROW4| C F I
should combine into
A
B
C
D
E
F
G
H
I
The first row of each column needs to be skipped.
Try this. Click anywhere in your range of data and then use this macro:
Sub CombineColumns()
Dim rng As Range
Dim iCol As Integer
Dim lastCell As Integer
Set rng = ActiveCell.CurrentRegion
lastCell = rng.Columns(1).Rows.Count + 1
For iCol = 2 To rng.Columns.Count
Range(Cells(1, iCol), Cells(rng.Columns(iCol).Rows.Count, iCol)).Cut
ActiveSheet.Paste Destination:=Cells(lastCell, 1)
lastCell = lastCell + rng.Columns(iCol).Rows.Count
Next iCol
End Sub
You can combine the columns without using macros. Type the following function in the formula bar:
=IF(ROW()<=COUNTA(A:A),INDEX(A:A,ROW()),IF(ROW()<=COUNTA(A:B),INDEX(B:B,ROW()-COUNTA(A:A)),IF(ROW()>COUNTA(A:C),"",INDEX(C:C,ROW()-COUNTA(A:B)))))
The statement uses 3 IF functions, because it needs to combine 3 columns:
For column A, the function compares the row number of a cell with the total number of cells in A column that are not empty. If the result is true, the function returns the value of the cell from column A that is at row(). If the result is false, the function moves on to the next IF statement.
For column B, the function compares the row number of a cell with the total number of cells in A:B range that are not empty. If the result is true, the function returns the value of the first cell that is not empty in column B. If false, the function moves on to the next IF statement.
For column C, the function compares the row number of a cell with the total number of cells in A:C range that are not empty. If the result is true, the function returns a blank cell and doesn't do any more calculation. If false, the function returns the value of the first cell that is not empty in column C.
I created an example spreadsheet here of how to do this with simple Excel formulae, and without use of macros (you will need to make your own adjustments for getting rid of the first row, but this should be easy once you figure out how my example spreadsheet works):
https://docs.google.com/a/umich.edu/spreadsheet/ccc?key=0AuSyDFZlcRtHdGJOSnFwREotRzFfM28tWElpZ1FaR2c#gid=0
Not sure if this completely helps, but I had an issue where I needed a "smart" merge. I had two columns, A & B. I wanted to move B over only if A was blank. See below. It is based on a selection Range, which you could use to offset the first row, perhaps.
Private Sub MergeProjectNameColumns()
Dim rngRowCount As Integer
Dim i As Integer
'Loop through column C and simply copy the text over to B if it is not blank
rngRowCount = Range(dataRange).Rows.Count
ActiveCell.Offset(0, 0).Select
ActiveCell.Offset(0, 2).Select
For i = 1 To rngRowCount
If (Len(RTrim(ActiveCell.Value)) > 0) Then
Dim currentValue As String
currentValue = ActiveCell.Value
ActiveCell.Offset(0, -1) = currentValue
End If
ActiveCell.Offset(1, 0).Select
Next i
'Now delete the unused column
Columns("C").Select
selection.Delete Shift:=xlToLeft
End Sub
Function Concat(myRange As Range, Optional myDelimiter As String) As String
Dim r As Range
Application.Volatile
For Each r In myRange
If Len(r.Text) Then
Concat = Concat & IIf(Concat <> "", myDelimiter, "") & r.Text
End If
Next
End Function
Related
I am entering a dynamic data into excel sheet from a textbox. The problem is that it enters letter by letter in every cell.
This is the code I have tried:
>>function bntEnterData_callback(hObject,eventdata,handles)
>>val1 = get(handles.txt1,'string'));
>>val2 = get(handles.txt2,'string'));
>>val3 = get(handles.txt3,'string'));
>>values = [ val1 val2 val3]
>>filename= 'try.xls';
>>sheet= 1;
>>xkRange= 'A2';
>>xlswrite(filename,values,sheet,xlRange);
Assuming your handles.txt* are edit uicontrols, the 'String' property is going to be a character vector. Concatenating multiple character vectors just creates a longer vector:
a = 'foo';
b = 'bar';
values = [a b]
Which creates:
values =
'foobar'
When not explicitly provided a range of cells to write to, xlswrite will interpret the input single cell (or the default A1) as the starting point, and write all elements of the input array using the single cell as the origin. Because 'foobar' is an array of characters, this gives the expected behavior of:
To fix this, concatenate into a cell array:
a = 'foo';
b = 'bar';
values = {a b};
filename= 'try.xls';
sheet= 1;
xlRange= 'A2';
xlswrite(filename,values,sheet,xlRange);
I have a worksheet that I need to pull in data from another file. I need a Macro to take the values in Column A and Column D respectively in each row of the active worksheet and compare the those values with values in the other file, Columns A and F respectively. If a match is found somewhere within the rows of this worksheet, then I want it to take the values within Column B and C and place them into Column B and C of the first worksheet. I am new to building macros and this one just has me stumped on how to get what I need. Can anyone help?
Example of Worksheets:
First Worksheet
Second Worksheet
I figured out a solution. I combined the top assembly and the comp item and did a VLOOKUP for both of the columns. It's sloppy for it works...
Columns("B:B").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Sheets("Potential Issues").Select
Range("B1").Select
ActiveCell.FormulaR1C1 = "Unique Top Assembly Comp Item Number"
Range("C1").Select
ActiveCell.FormulaR1C1 = "NHA Item"
Range("D1").Select
ActiveCell.FormulaR1C1 = "NHA User Item Type"
With ActiveSheet.Range("A2").CurrentRegion
If .Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then
With .Columns(2)
.Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible).FormulaR1C1 = "=RC[-1]&RC[3]"
End With
End If
End With
Cells.Select
Selection.Copy
Range("A1").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("A1").Select
With ActiveSheet.Range("A2").CurrentRegion
If .Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then
With .Columns(3)
.Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible).FormulaR1C1 = _
"=VLOOKUP(C[-1],'B2.0 Buys Exploded BOM'!C2:C4,2,0)"
End With
End If
End With
With ActiveSheet.Range("A2").CurrentRegion
If .Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then
With .Columns(4)
.Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible).FormulaR1C1 = _
"=VLOOKUP(C[-2],'B2.0 Buys Exploded BOM'!C2:C4,3,0)"
End With
End If
End With
Cells.Select
Selection.Copy
Range("A1").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Columns("B:B").Select
Selection.ColumnWidth = 21
Columns("C:C").Select
Selection.ColumnWidth = 24
Columns("D:D").Select
Selection.ColumnWidth = 15
Range("B:B,G:H").Select
Selection.EntireColumn.Hidden = True
Range("A1").Select
I have a cell array (2000*10) with each cell containing a string such as '25:20:55'.
I want to write a function that accepts 10 inputs (say '25:02:33', '58:69:88', '25:54:96', '48:58:36', '58:54:88' and so on) and looks for a match in each column corresponding to input value for that particular column (i.e. the first input data corresponds to 1st column, 2nd to 2nd column of the stored data and so on.
How can I write a function for the above comparison?
Assuming the cell array contains strings, you can find matches using strcmp:
input = {'25:02:33', '58:69:88', '25:54:96', '48:58:36', '58:54:88'};
match_idx = strcmp(repmat(input, size(cell_data,1),1), cell_data);
If you only want to know if there are matches in the respective columns at all and do not care about the line index of the match, you can do
match = any(match_idx,1);
Use ismember
ismember(your_var, your_cell);
e.g.
c = {'a', 'b', 'c', 'd'};
ismember('b', c)
ans =
1
ismember('q', c)
ans =
0
In your case, something like could work
function arr = myfun(inputvec, inputmat)
for i=1:length(inputvec) %// where inputvec is the cell-vector with the strings you want to search for
arr(i) = ismember(inputvec{i}, inputmat{:,i});
end
I have created a matrix with row 1 full of strings and 4 other rows with numbers. They are created in a handle class with the object "Projekter".
So in the object "Projekter" row 1, the first value is blank, but the second value is 'Ole'. So I know that 'Ole' is in (1,2). x is the name/string I want to search for, which in this case is 'Ole'.
As you see below it should search row 1 from column 2 untill the last name/string and if i = 'Ole', it should bring me the value 2 because " i " should be equal 2.
A is just a controller if the function works, but at this point it doesn't.
The error it gives is "Undefined function 'eq' for input arguments of type 'cell'."
How do I fix this so it return the " i " value when the statement is correct?
Thank you in advance!
function number(obj,x)
A = [];
for i = 2:size(obj.Projekter,2)
if obj.Projekter(1,i)==x
A = A + 1;
end
end
disp(A)
end
Maybe you have to index the cell content:
your_cell = {'a_string'};
your_string = your_cell{1};
function [returnValue] = number(obj,x)
for i = 2:size(obj.Projekter,2)
if obj.Projekter{1,i}==x
returnValue = i;
return;
end
end
end
Note the change from obj.Projekter(1,i)==x to obj.Projekter{1,i}==x (use curly braces instead of parens). I have then specified that returnValue will hold the value that should be returned by doing function [returnValue] = number(obj,x). We then set returnValue equal to i and return from the function when the condition of the if statement is true.
As suggested in the comments, it is probably better to do:
function [returnValue] = number(obj, x)
returnValue = find(strcmp(x, obj.Projekter) == 1);
strcmp(x, obj.Projektor) will give you an array the length of obj.Projekter with 1's wherever the strings match, and 0's where they don't, you can then find the indices that are set to 1. This has the added benefit of
not using a loop so it's faster
Giving you every occurrence of a match, not just the first one.
I have a matlab program where I am importing some arrays from excel. I am trying to write an if statement that looks in the first array, say:
Thing-1 Thing-1 Thing-3 Thing-5
If a column is a "Thing-1", then it goes to a different array, and calculates 3 values that are to be given different variable names...any guidance would be much appreciated! Thanks!
You need a function like vlookup as in Excel.
I have written one. Here is the source code:
function [content, index] = vlookup(m, e, column, lookcolumn)
if isempty(m) || isempty(e), return; end
if nargin <= 3, lookcolumn = 1; end
isechar = ischar(e);
assert(isechar || isnumeric(e), 'the second parameter must be a string or numeric');
if iscell(m)
content = {}; index = [];
if isechar
index = find(strcmp(e, m(:, lookcolumn)));
content = m(index, column);
else
for i = 1:size(m, 1)
if isnumeric(m{i, lookcolumn}) && m{i, lookcolumn} == e
content = [content; m(i, column)]; %#ok<*AGROW>
index = [index; i];
end
end
end
else
assert(~isechar, 'When the first para is a matrix, the second para must be numeric');
index = find(m(:, lookcolumn) == e);
content = m(index, column);
end
The question is... not very clear, but let me try and give you some suggestions.
Say you read some data from an Excel workbook in which the first row is headers, followed by lots of rows with numbers.
[num,txt] = xlsread(excelFileName);
so that num contains the numeric data and txt the string column headers.
Then you can check for the string Thing-1 in the column headers. thingOneIdx is an array with indices into the columns of the header. In your example, it would be [1 2], since the first two columns are Thing-1.
thingOneIdx = find(strcmp('Thing-1',txt));
You can create three cell arrays, firstValue, secondValue, and thirdValue that will store the results of the three calculations. If you need to keep the Thing-1 data around in an additional array, you can do that analogously.
%# define cell arrays (do it in one go using deal)
[firstValue,secondValue,thirdValue] = deal(cell(length(thingOneIdx),1));
%# for simplicity and readability, loop through isThingOneIdx to assign data
for ct = 1:length(thingOneIdx)
myIdx = thingOneIdx(ct);
firstValue{ct} = someCalculation(num(myIdx,:));
secondValue{ct} = someOtherCalculation(num(myIdx,:));
%# etc
end