Excel VBA; Search rows grabbing values and pasting them into another worksheet - vba

I have two workbooks;
(WB1) with two sheets; "Input" and "Output"
and
(MacroWB) with the macro and a "Column Header" list.
Example file: "Messy" sheet = input, "Organized" = output
https://drive.google.com/file/d/0B-leh2Ii2uh9bDBFbDBHbGcxbUU/view?usp=sharing
I need help coding a macro to do the following:
1) Create a loop to go through each row of the "Input" sheet searching for values matching cells in the "Column Header" list.
2) When a matching value is found; take the data from the cell immediately to it's right (in the "Input" sheet) and paste it into the corresponding column of the "Output" worksheet.
3) Once every "Column Header" item has been searched/pasted for that row; move to the next row of the "Input" sheet. Rinse and repeat until all rows of the "Input" sheet have been searched/pasted.
Here is an example, the letters are to be column headers and the numbers are to be copied to the appropriate "Output" sheet column.
https://drive.google.com/file/d/0B-leh2Ii2uh9TXRGTnFDRU1jY0U/view?usp=sharing
Keep in mind that the actual data file has ~50 columns and ~3000 rows.
Also that the data is not all Letter/Numbers like the table above, it is more like the data in the linked .xlsx file.
If there is anything I haven't been clear about, please ask and I will try my best to clarify. Also I may be WAY over thinking this, if so.. please let me know.
THANK YOU ANYONE THAT CAN GET ME GOING IN THE CORRECT DIRECTION!!!
-Joe

Skip the the VBA and use Text to Columns the Data tab. I'malways copying html and its works 99% of the time. If the html is pretty and properly formated you may get away with using the fixed width option, otherwise gor for the delimted and choose "tab". If tab doesn't work try using spaces, assuming that your cells don't contain spaces.
The other option that I've had work on rare occasions that text to columns doesn't is simply saving the text in word and saving as rtf and then opening that in notepad++ (which everyone should have.) Copy from ++ to excel and that usually fixes the problem.
EDIT: If you right click before pasting and click "paste special" this regularly helps with html pasting.

In your sample file, I used the following formula in A2 of Organized sheet (assumed 50 as max columns in Messy):
=IFERROR(OFFSET(Messy!A1,0,MATCH(Organized!A$1,OFFSET(Messy!A1,0,0,1,50), )),"")
Dragging it to H11 produced the following result:
The sample data is not complete, and some 'tags' in Messy sheet are not consistent (SiteID vs SITE_ID), but it should help you get started.

Related

Preventing excel from altering cell contents to take literal values

I have scripted out a module that reads data I paste in from a SQL dump, and converts it into a data insert script to SQL. It is working great, only problem is for cells that contain items like:
11-20
instead of filling my value as '11-20', it is converting it to '20-Nov'.
I have adjusted how i read the cell from text to value to value2, Text comes the closest to right (rest do a math calc that tosses my overall sheet off even worse, namely dates). I have also tried such things as a Range("X:X").clear and clearformat as well. This also does not do the trick.
How do I force my string read of this cell to be the literal CSV content, and ignore the formula/calculations that excel is tossing at me?
EDIT:
Thanks to BraX for the solution!
I was unable to accomplish this by copying from one tab to the next within Excel, but i did get it to work by pausing my operation with a message box prompting the user to simply navigate to SQL and put the contents of the data in to the clip board. This works perfectly now!
Cells.Select
Selection.NumberFormat = "#"
MsgBox "Please navigate to SQL and copy your data to be insurted, including headers. When done click OK"
Range("A1").Select
ActiveSheet.Paste
Before adding the data to the sheet, set the NumberFormat to # for the affected columns.
Example:
ActiveWorkBook.WorkSheets("Sheet1").Range("A:A").NumberFormat = "#"
That will format the values to Text and prevent them from being interpreted as a Date when the data is added. Once Excel decides it's a date, it's too late.
i am pretty sure all it takes is to format the cells, right click on the range of cells you want formatted as plain text, click "FORMAT CELLS" and under the "NUMBER TAB" it shows the "CATEGORY" of the type of formatting, e.g: "General, Number, Currency, etc" select where it says "Text" and click ok, any text will be evaluated the same way you write it, so even if you write "11-5-18" it will be just that and won't be considered a date or anything.

Copy / Paste w/ Formatting from single cell to merged cells

I have an Excel sheet with multiple pages. One of two pages is a data tab and has a long list of names and then several columns of data. (Cells A1 - F1 are headers, A2-A20 are named, B2-F20 are different pieces of data regarding each name). The second page pulls specific data (index function) from the data tab.
I have bolded info on the data tab, and when you index something, you lose formatting. Normally, I could create a VBA code to copy/paste special into the format (to preserve the bolded words), but the nature of the formatting page means it has to have merged cells. I can copy/paste the info but it does not preserve the formatting. If I try to paste special, I get the error "This operation requires the merged cells to be identically sized".
Is there a way to paste and preserve the bolded text without unmerging the formatted sheet?
You can do something like this:
Worksheets("Sheet2").Range("A1").Value = Worksheets("Sheet1").Range("A1").Value
Worksheets("Sheet2").Range("A1").Font.FontStyle = Worksheets("Sheet1").Range("A1").Font.FontStyle
This will transfer the font style to the from the data cell to the target cell, regardless if the cell is merged or not.

Lookup function in multiple sheets data

I have multiple sheets of data and I want to make it in one sheet (All of them are in the same workbook). Link to the excel file.
I tried to use Hlookup function in excel file, something like below:
=HLOOKUP("University",Sheet1!$A$1:$G$2, 2, FALSE).
But, since I have more than 100 sheets of data, I want to find a way to drag the function and auto generate the function below the 2nd row. I have tried to use indirect function by setting a reference column in front as below but cannot deal with it.
=HLOOKUP("University", 'INDIRECT(A3)'!$A$1:$G$2, 2, FALSE)
My next option is VB code. But, I am new to VB. Anybody can help on it?
Place your individual sheet names in column H of the Summary sheet and the row number in column I (as helper columns) and write this formula in cell A2 of the summary sheet.
=IFERROR(HLOOKUP(A$1,INDIRECT($H2&"!A1:G"&$I2),$I2,0),)
and drag to column F and down for as many sheet rows combos you have. I used 10 rows but you can obviously make it longer or shorter as neeed.
When you are done you can filter on 0 in column A and remove any lines with no data.
If your sheet names have spaces in them, you'll need to adjust the INDIRECT formula to this:
INDIRECT("'"&$H2&"'!A1:G"&$I2)
best way would be "defined names" + INDIRECT + HLOOKUP (or LOOKUP) like:
defined names
name: SList
formula: =MID(TRANSPOSE(GET.WORKBOOK(1))&T(NOW()),FIND("]",TRANSPOSE(GET.WORKBOOK(1))&T(NOW()))+1,255)
formula in cells: (this in A2 then simply autofill to G2 and thenn everything down) (you'll get a row with 0's between the sheets, which can be filtered out or deleted later (copy/paste values))
=IFERROR(HLOOKUP(A$1,INDIRECT("'"&INDEX(SList,COUNTIF($A$1:$A1,0)+2)&"'!$A:$G"),$H2,0),"")
Set H2 to 2 and for H3: (autofill down from H3)
=MAX(($H2+1)*($A2>0),2)
works perfectly for me LINK
No manual typing of sheetnames or something like that (only Column H:H as helper). Youll get rows's with 0's every time a new sheet is selected which can be filtered out. (or if you copy/paste values also can be deleted)
the +2 at ...st,COUNTIF($A$1:$A1,0)+2)&... simply tells to start with sheet 2 (if summary is the first). You may change it to +1 if you want to lookup starting with the first sheet.
Assuming you already have all 100+ sheet names typed out in column A, this will work whether or not you have spaces in the sheet names:
=HLOOKUP("University", OFFSET(INDIRECT(ADDRESS(1,1,1,1,A2)),0,0,2,7),2,FALSE)

Convert xls File to csv, but extra rows added?

So, I am trying to convert some xls files to a csv, and everything works great, except for one part. The SaveAs function in the Excel interop seems to export all of the rows (including blank ones). I can see these rows when I look at the file using Notepad. (All of the rows I expect, 15 rows with two single quotes, then the rest are just blank). I then have a stored procedure that takes this csv and imports to the desired table (this works on spreadsheets that have been manually converted to csv (e.g. open, File--> Saves As, etc.)
Here is the line of code I am using for my SavesAs in my code. I have tried xlCSV, xlCSVWindows, and xlCSVDOS as my file format, but they all do the same thing.
wb.SaveAs(aFiles(i).Replace(".xls", "B.csv"), Excel.XlFileFormat.xlCSVMSDOS, , , , False) 'saves a copy of the spreadsheet as a csv
So, is there some additional step/setting I need to do to not get the extraneuos rows to show up in the csv?
Note that if I open this newly created csv, and then click Save As, and choose csv, my procedure likes it again.
When you create a CSV from a Workbook, the CSV is generated based upon your UsedRange. Since the UsedRange can be expanded simply by having formatting applied to a cell (without any contents) this is why you are getting blank rows. (You can also get blank columns due to this issue.)
When you open the generated CSV all of those no-content cells no longer contribute to the UsedRange due to having no content or formatting (since only values are saved in CSVs).
You can correct this issue by updating your used range before the save. Here's a brief sub I wrote in VBA that would do the trick. This code would make you lose all formatting, but I figured that wasn't important since you're saving to a CSV anyway. I'll leave the conversion to VB.Net up to you.
Sub CorrectUsedRange()
Dim values
Dim usedRangeAddress As String
Dim r As Range
'Get UsedRange Address prior to deleting Range
usedRangeAddress = ActiveSheet.UsedRange.Address
'Store values of cells to array.
values = ActiveSheet.UsedRange
'Delete all cells in the sheet
ActiveSheet.Cells.Delete
'Restore values to their initial locations
Range(usedRangeAddress) = values
End Sub
Tested your code with VBA and Excel2007 - works nice.
However, I could replicate it somewhat, by formatting an empty cell below my data-cells to bold. Then I would get empty single quotes in the csv. BUT this was also the case, when I used SaveAs.
So, my suggestion would be to clear all non-data cells, then to save your file. This way you can at least exclude this point of error.
I'm afraid that may not be enough. It seems there's an Excel bug that makes even deleting the non-data cells insufficient to prevent them from being written out as empty cells when saving as csv.
http://answers.microsoft.com/en-us/office/forum/office_2010-excel/excel-bug-save-as-csv-saves-previously-deleted/2da9a8b4-50c2-49fd-a998-6b342694681e
Another way, without a script. Hit Ctrl+End . If that ends up in a row AFTER your real data, then select the rows from the first one until at least the row this ends up on, right click, and "Clear Contents".

Major formatting issue in Excel - VLOOKUP

I need help with a formatting issue in Excel, which is interfering with the VLOOKUP function in my Excel sheet.
I have two sheets with more than 20,000 column values as lookup, and the same number of values for reference. All the values in both cells are weirdly formatted, some with green triangles at the upper left corner of cells, some are text, etc.
Is there a way in Excel using a macro/VBA to remove or make all formatting similar in both sheets? The reason for VBA is because the person who is going to work with this file needs everything automated and is not familiar with Excel at all. I already have the VLOOKUP function in the cells, I just need to work with the formatting.
Well, I fight with partial lookups this way:
In the items array, I create new empty FIRST column and then place formula
="+"&B2
This will take the content of Cell B2 and add + in the front of it.
When I do vlookup, I add "+" to searcheable value
=VLOOKUP("+"&A6,A:O,2,FALSE)
Therefore, instead of comparing for example Strings and numbers, I compare Strings, by adding "+" in the front.
Another technique, is to kill all formatting:
Select whole column, click DATA-TEXT TO COLUMNS-DELIMITED and then DESELECT ALL DELIMITERS. Click Finish. This will clear your formatting.
===========================================================================
This is the VBA solution you asked for:
Call it from Excel
=GetLookup(G2,A:C)
Here is VBA:
Function GetLookup(LOOKFOR As String, RANGEARRAY As Range) As String
GetLookup = Application.WorksheetFunction.VLookup("+" & LOOKFOR, RANGEARRAY, 3, False)
End Function
Good luck!
I'm assuming the data type in all of the cells is the same, or you want it to all be the same. The following steps will make the cells a uniform type:
Save your workbook, in case this does not do as you require
Select all cells you wish to be of the same cell type
Press Ctrl+1, on the "Number" tab, select the type you wish these cells to take. Press OK.
Open the VBA editor using Alt+F11
Open the immediate window with Ctrl+G
Type the following: for each cell in selection : cell.formula = cell.value : next cell
Press enter (you may have to wait a few seconds).
If you take this action with the same data type (e.g. choose "Text" for both ranges in step 3) on both your ranges you should be "comparing apples with apples" and your VLOOKUP should function as required.
Hope this helps.
Edit: formatting, clarification