I've looked already but what I found so far is exporting to a existing excel sheet, what I need is to make a copy of an existing excel template I have and pass my data there. I just need to be pointed in the right way, hope I'm clear enough.
EDIT
I have an application working on Java to which I will add this.
Assuming that you ask about SQL Server, you can create 2 step job, one for copying your xls, and in second step using openrowset/insert into your copied excel file.
Here is Tsql which copies template and also sends an email, and info about xp_cmdshell https://msdn.microsoft.com/en-us/library/ms190693.aspx
DECLARE #cmd varchar(512)
DECLARE #fd varchar(512)
DECLARE #odbc varchar(128)
DECLARE #db varchar(128)
SELECT #fd = 'D:\Reports\Exact\ByWeek' + CONVERT(VARCHAR(10), GETDATE()-8,120)+'_'+CONVERT(VARCHAR(10), GETDATE(),120)+'.xls'
SELECT #cmd = 'copy D:\Reports\System\shipments_week.xls ' + #fd
EXEC MASTER..XP_CMDSHELL #cmd, NO_OUTPUT
SET #odbc = 'Microsoft.Jet.OLEDB.4.0'
SET #db = 'Excel 8.0;Database=' + #fd
exec('INSERT INTO OPENrowset(''' + #odbc + ''',''' + #db + ''',''SELECT
OrderNr,Debtor,SUM_NSHIPPED,SUM_TOTAL,PERC_NSHIPPED,ORDDAT,INVDAT,ORD_SYSCREATED,HIST_LAST_MODIFIED,PT_WZ_SENT
FROM [Shipped$]'')
SELECT * FROM salag_shipmentsbyWeek')
exec('INSERT INTO OPENrowset(''' + #odbc + ''',''' + #db + ''',''SELECT
OrderNr,Debtor,SUM_NSHIPPED,SUM_TOTAL,PERC_NSHIPPED,ORDDAT,INVDAT,ORD_SYSCREATED,HIST_LAST_MODIFIED,PT_WZ_SENT
FROM [SB$]'')
SELECT * FROM salag_shipmentsbyWeek WHERE Debtor NOT LIKE ''%CASTORAMA%'' AND Debtor NOT LIKE ''Praktiker%''')
DECLARE #Body VARCHAR(4096)
DECLARE #BodyType VARCHAR(16)
DECLARE #path VARCHAR(128)
DECLARE #f VARCHAR(32)
DECLARE #topic VARCHAR(128)
SELECT #f = CONVERT(VARCHAR(10), GETDATE()-8,120)+'_'+CONVERT(VARCHAR(10), GETDATE(),120)
SELECT #topic = 'New Report ['+ CONVERT(VARCHAR(10), GETDATE()-8,120)+'_'+CONVERT(VARCHAR(10), GETDATE(),120) + ']'
SELECT #path = '\\appsrv\Reports\Exact\ByWeek' + CONVERT(VARCHAR(10), GETDATE()-8,120)+'_'+CONVERT(VARCHAR(10), GETDATE(),120)+'.xls'
SELECT #Body = 'New Scan Report has been created: '+#f+' '+ #path
SELECT #BodyType = 'HTMLBody'
exec sp_send_cdosysmail 'Reports Info ','reports#foo ar.com',#topic, #Body, #BodyType
I was able to achieve what I was looking for using JExcel and it was pretty easy, here I will share my code and hope it helps someone in the future. Sorry its not properly commented yet, I will later post an update.
Db_Connect connection = new Db_Connect();
conn = connection.connect();
String originalFile = "C:\\Users\\Geni\\Desktop\\Book1-Template-new.xls";
date = date.replace("/", "-");
SimpleDateFormat myDate = new SimpleDateFormat("yyyy-MM-dd");
try{
Workbook original = Workbook.getWorkbook(new File(originalFile));
WritableWorkbook copy = Workbook.createWorkbook(new File(date+".xls"), original);
java.util.Date format = myDate.parse(date);
java.sql.Date newDate = new java.sql.Date(format.getTime());
String sql = "SELECT Name, sporecount.* FROM sporesfungi "
+ "INNER JOIN sporecount ON sporesfungi.IDSpore = sporecount.IDSpore"
+ "WHERE Date = ? ORDER BY TraceNum";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setDate(1, newDate);
rs = statement.executeQuery();
/*stmt = conn.createStatement();
rs = stmt.executeQuery(sql);*/
WritableSheet sheet = copy.getSheet(0);
WritableCell cell;
String spore;
while(rs.next()){
for(int i = 2; i < 64 ;i++){
cell = sheet.getWritableCell(1,i);
spore = cell.getContents();
if(rs.getString("Name").equals(spore)){
Number l1 = new Number(14-rs.getInt("TraceNum"),i,rs.getInt("Amount")) ;
sheet.addCell(l1);
}
}
}
copy.write();
copy.close();
original.close();
}
catch (BiffException | IOException e) {
}
Related
I am inserting data from a Text file to table.
and the SPROC is as follows
ALTER PROCEDURE [dbo].[SPROC]
-- Add the parameters for the stored procedure here
#DBName VARCHAR(30),
#FirstLine VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #InsertQuery NVARCHAR(MAX), #Summary_ID INT
SET #InsertQuery = 'INSERT INTO ' + #DBName + '.[dbo].[Summary] VALUES ( ' + #FirstLine + '); SELECT SCOPE_IDENTITY()'
EXEC SP_EXECUTESQL #InsertQuery
END
Now the thing is, if it has 8 values it will get inserted. If 8 th Value is not there in the text file it is throwing Error column name or number of supplied values does not match table definition
How can i handle this error and If there is no value for 8th column it should insert the value as NULL.
Reading File code:
public static String[] ReadSummary_Into_Array(string filepath)
{
StreamReader sreader = null;
int counter = 0;
try
{
sreader = new StreamReader(filepath);
string line = sreader.ReadLine();
//condition to hanlde empty file
if (line == null) return null;
//condition to hanlde empty first line file
if (line == "") return new String[0];
FirstLine = line;
string cleaned_line = line.Replace("''", "'-'").Replace("','", "''");
string word = "";
List<string> data = new List<string>();
MatchCollection matches = Regex.Matches(cleaned_line, #"'([^']*)");
//String[] words = null;
foreach (Match match in matches)
{
word = match.ToString();
string word_edited = word.Replace("\'", "");
if (word_edited != string.Empty)
{
data.Add(word_edited);
counter++;
}
}
Summary = new String[counter];
Summary = data.ToArray(); //The Summary Line is reconstructed into a String array
return Summary;
}
If you dont have value then you must specify the column names.
Try like this
ALTER PROCEDURE [dbo].[SPROC]
-- Add the parameters for the stored procedure here
#DBName VARCHAR(30),
#FirstLine VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #InsertQuery NVARCHAR(MAX), #Summary_ID INT, #CountS INT
SET #CountS = len(#FirstLine) - len(replace(#FirstLine, ',', ''))
IF #CountS >= 7 THEN
SET #InsertQuery = 'INSERT INTO ' + #DBName + '.[dbo].[Summary] VALUES ( ' + #FirstLine + '); SELECT SCOPE_IDENTITY()'
ELSE
SET #InsertQuery = 'INSERT INTO ' + #DBName + '.[dbo].[Summary](SerialNumber,AssetNumber,SoftwareRev,TechName,StartTime,StopTime,Status) VALUES ( ' + #FirstLine + '); SELECT SCOPE_IDENTITY()'
END IF
EXEC SP_EXECUTESQL #InsertQuery
END
Similar as Vignesh, but in your C# code
if ( Regex.Matches( strLine, "," ).Count == 7)
{
strLine = strLine + ', null';
}
SELECT TOP #columnCount #columnName
FROM #tableName
I get the following error
Incorrect syntax near '#columnCount'.
What could be wrong?
If I change to
SELECT TOP (#columnCount) #columnName
FROM #tableName
I get the following error
Must declare the table variable "#tableName".
I run it from C#
A safe and secure way would be
DECLARE #columnCount INT = 100
DECLARE #columnName NVARCHAR(128) = 'YourColumnName'
DECLARE #tableName NVARCHAR(128) = 'YourTableName'
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'SELECT TOP (#columnCount) ' + QUOTENAME(#columnName) + N'
FROM ' + QUOTENAME(#tableName)
EXECUTE sp_executesql #Sql
,N'#columnCount INT'
,#columnCount
You need dynamic SQL to accomplish what you're trying to do.
DECLARE #sql VARCHAR(max);
SET #sql = 'SELECT TOP ' + #columnCount + ' ' + #columnName + ' FROM ' + #tableName;
EXEC(#sql);
The variables used need to be converted appropriately.
Read more in the documentation
Column lists and Table names cannot be parameters. However, since you are running this from C# you are technically already using Dynamic SQL (unless you are calling a stored procedure with those params but there is no mention here of stored procedures being used so for now I will assume not). When building the SQL in C#, you need to concatenate the Column List and Table Name into the query but you can still use a parameter for the value used by the TOP() operator:
SqlConnection _Connection = new SqlConnection("connection string");
SqlCommand _Command = new SqlCommand();
SqlDataReader _Reader = null;
string _Query;
string _TableName = "dbo.MyTable";
string _ColumnList = "Field1, Field2 AS [AliasedName], Field3";
int _NumberOfRows = 12;
_Query = String.Concat("SELECT TOP (#NumberOfRows) ",
_ColumnList, " FROM ", _TableName);
SqlParameter _NumRows = new SqlParameter("#NumberOfRows", SqlDbType.Int);
_NumRows.Value = _NumberOfRows;
try
{
_Connection.Open();
_Reader = _Command.ExecuteReader();
// do stuff
}
finally
{
_Reader.Close();
_Connection.Close();
}
Of course, you could also just concatenate the #NumberOfRows value directly into the query as well, but keeping it as a parameter will allow for Query Plan re-use if running this query multiple times with the same values for ColumnList and TableName but changing the #NumberOfRows value.
I've written the below code to set filepath column in my table as 'F:\DataMigration\Wise\DELTA_20121008\Attachments\SR\SR_1.txt'
where SR_1 is file_name column
.txt is file_ext column from my table.
but after executing following procedure, I'm getting filepath column in table as
'F:\DataMigration\Wise\DELTA_20121008\Attachments\file_name.file_ext'
means It's treating column names as string, how i can make it as column so it will
use values in that column.
alter procedure [dbo].[WISEMissingAttachmentReportGenerator]
(
#tablename varchar(255), #pathonlocal nvarchar(255)
)
as
begin
--step 1
exec dbo.proc_alter_table #tablename
--step 2
EXEC ('update '+ #tablename +
' set filepath = '''+ #pathonlocal + ' file_name'+'.'+'file_ext''')
EXEC('Select * from '+#tablename)
end
exec [dbo].[WISEMissingAttachmentReportGenerator] [WISE.Non_VP_Service_Request_Attachments_File_Check_Analysis],
N'F:\DataMigration\Wise\DELTA_20121008\Attachments\SR\'
Try;
EXEC('UPDATE '+ #tablename +
' SET filepath = '''+ #pathonlocal + ''' + file_name + '''+'.'+''' + file_ext')
Equal as;
UPDATE [YourTable] SET filepath = 'YourPath' + file_name + '.' + file_ext
Try changing your statement to this:
EXEC ('update '+ #tablename +
' set filepath = '''+ #pathonlocal + ''' + file_name + ''.'' + file_ext')
declare #tblnm varchar(20) = 'test'
declare #upda varchar(20) = 'update '
declare #set varchar(25) = ' set'
declare #id varchar(25) = ' id'
declare #cmd varchar(1000)
set #cmd = #upda + #tblnm + #set + #id + '=7'
exec(#cmd)
SAMPLE SQL UPDATE QUERY - FOR BUILDING TABLENAME DYNAMICALLY
EXECUTED GUYS - THIS IS CALL JUGAAAAAAAAAD [NO NEED TO GET INTO ''' STUFF]
I'm having some trouble executing a dynamic query inside my SP, and I thought asking for some help as I can't execute it correctly no matter what I try:
I have tried:
SET #subWorksQuery =
'UPDATE JK_SubscriberWorks SET ' +
'update_date = convert(datetime, ''' + #dateNow + ''', 103), ' +
'challenge_' + convert(nvarchar(2), #challengeDay) + '_q = ''' + #challengeQuestion + ''', ' +
'challenge_' + convert(nvarchar(2), #challengeDay) + '_a = ''' + #challengeAnswer + ''' ' +
'WHERE subscriberwork_id = '' + convert(nvarchar(10), #subscriberWorksId) + '';';
execute #execReturn = #subWorksQuery
but I always get:
Msg 203, Level 16, State 2, Procedure sp_InsertChallengeResponse_test,
Line 112
The name 'UPDATE JK_SubscriberWorks SET update_date = convert(datetime, '23-12-2011 23:35:17', 103), challenge_23_q =
'Hvilket år blev Klasselotteriet omdannet til et aktieselskab? Få hjælp til svaret.',
challenge_23_a = '1992' WHERE subscriberwork_id = ' +
convert(nvarchar(10), #subscriberWorksId) + ';' is not a valid
identifier.
Removing the UPDATE statement from that error and run it independently, it runs and performs the update
If I use sp_executesql like
SET #subWorksQuery =
N'UPDATE JK_SubscriberWorks SET ' +
'update_date = #a, ' +
'challenge_' + convert(nvarchar(2), #challengeDay) + '_q = #b, ' +
'challenge_' + convert(nvarchar(2), #challengeDay) + '_a = #c ' +
'WHERE subscriberwork_id = #d;';
SET #parmDefinition = N'#a datetime, #b nvarchar(250), #c nvarchar(500), #d decimal';
execute sp_executesql
#subWorksQuery,
#parmDefinition,
#a = #CreateDate, #b = #challengeQuestion, #c = #challengeAnswer, #d = #subscriberWorksId;
It never performs the UPDATE, but does not throw any error.
What am I missing here?
Run it like this:
execute (#subWorksQuery)
[you won't be getting anything back from the update statement in the variable, and you can't run like this execute (#execReturn = #subWorksQuery) ]
Without parentheses it seems to be starting parsing, assuming it is a stored procedure name, but failing when it hits the max length for one.
In saying that, it is better to use sp_executesql with parameters.
I am not sure what you are looking for in the return value, but if you just need the count of rows affected, that should be easy to obtain.
Change:
execute #execReturn = #subWorksQuery
to:
execute (#subWorksQuery)
select #execReturn = ##ROWCOUNT
just a thought...your #d parameter is a decimal value. Is your id an int? is there a possible data type conflict?
how are your sp input parameters defined? Could you post the full sp?
Dave
I am working on a search query (with an asp.net 3.5 front end) which seems quite simple, but is quite complex.
The complete query is:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[usp_Item_Search]
#Item_Num varchar(30) = NULL
,#Search_Type int = NULL
,#Vendor_Num varchar(10) = NULL
,#Search_User_ID int = 0
,#StartDate smalldatetime = NULL
,#EndDate smalldatetime = NULL
AS
DECLARE #SQLstr as nvarchar(4000)
Set #SQLstr = 'SELECT RecID, Vendor_Num, Vendor_Name, InvoiceNum, Item_Num,
(SELECT CONVERT(VARCHAR(11), RecDate, 106) AS [DD MON YYYY]) As RecDate, NeedsUpdate, RecAddUserID FROM [tbl_ItemLog] where 1=1 '
IF (#Item_Num IS NOT NULL and LTRIM(#Item_Num) <> '')
Begin
If #Search_Type = 0
BEGIN
Set #SQLstr = #SQLstr + 'AND Item_Num LIKE ''' + #Item_Num + '%'''
END
If #Search_Type = 1
BEGIN
Set #SQLstr = #SQLstr + 'AND Item_Num LIKE ''%' + #Item_Num + '%'''
END
If #Search_Type = 2
BEGIN
Set #SQLstr = #SQLstr + 'AND Item_Num LIKE ''%' + #Item_Num + ''''
END
End
IF (#Vendor_Num IS NOT NULL and LTRIM(#Vendor_Num) <> '')
Begin
Set #SQLstr = #SQLstr + ' AND Vendor_Num = ''' + #Vendor_Num + ''''
End
IF (#Search_User_ID IS NOT NULL and #Search_User_ID > 0)
Begin
Set #SQLstr = #SQLstr + ' AND RecAddUserID = ' + convert(nvarchar(20),#Search_User_ID)
End
Set #SQLstr = #SQLstr + ' AND (RecDate BETWEEN ''' + convert(nvarchar(10),#StartDate,106) + ''' AND ''' + convert(nvarchar(10),#EndDate,106) + ''')'
PRINT (#SQLstr)
--Execute (#SQLstr)
When I pass all empty parameter values, I get an error:
"Failed to convert parameter value
from a String to a Int32."
The asp.net code that is calling the stored proc is:
//Display search results in GridView;
SqlConnection con = new SqlConnection(strConn);
//string sqlItemSearch = "usp_Item_Search";
SqlCommand cmdItemSearch = new SqlCommand(sqlItemSearch, con);
cmdItemSearch.CommandType = CommandType.StoredProcedure;
cmdItemSearch.Parameters.Add(new SqlParameter("#Item_Num", SqlDbType.VarChar, 30));
cmdItemSearch.Parameters["#Item_Num"].Value = txtItemNumber.Text.Trim();
cmdItemSearch.Parameters.Add(new SqlParameter("#Search_Type", SqlDbType.Int));
cmdItemSearch.Parameters["#Search_Type"].Value = ddlSearchType.SelectedItem.Value;
cmdItemSearch.Parameters.Add(new SqlParameter("#Vendor_Num", SqlDbType.VarChar, 10));
cmdItemSearch.Parameters["#Vendor_Num"].Value = txtVendorNumber.Text.Trim();
cmdItemSearch.Parameters.Add(new SqlParameter("#Search_User_ID", SqlDbType.Int));
cmdItemSearch.Parameters["#Search_User_ID"].Value = ddlSeachUser.SelectedItem.Value;
if (!string.IsNullOrEmpty(txtStartDate.Text))
{
cmdItemSearch.Parameters.Add(new SqlParameter("#StartDate", SqlDbType.DateTime));
cmdItemSearch.Parameters["#StartDate"].Value = Convert.ToDateTime(txtStartDate.Text.Trim());
}
else
{
cmdItemSearch.Parameters.Add(new SqlParameter("#StartDate", SqlDbType.DateTime));
cmdItemSearch.Parameters["#StartDate"].Value = Convert.ToDateTime("01/01/1996");
}
if (!string.IsNullOrEmpty(txtEndDate.Text))
{
cmdItemSearch.Parameters.Add(new SqlParameter("#EndDate", SqlDbType.DateTime));
cmdItemSearch.Parameters["#EndDate"].Value = Convert.ToDateTime(txtEndDate.Text.Trim());
}
else
{
cmdItemSearch.Parameters.Add(new SqlParameter("#EndDate", SqlDbType.DateTime));
cmdItemSearch.Parameters["#EndDate"].Value = Convert.ToDateTime(DateTime.Now);
}
con.Open();
SqlDataAdapter ada = new SqlDataAdapter(cmdItemSearch);
DataSet ds = new DataSet();
ada.Fill(ds);
gvSearchDetailResults.DataSource = ds;
gvSearchDetailResults.DataBind();
pnlSearchResults.Visible = true;
How can I resolve this?
You're not quite building the string correctly as far as I can tell. If no #Item_Num is passed in, you'll end up with no WHERE key word... you'll just have "FROM [tblItem_Log] AND..."
I would make all of the criteria appends be "AND ..." and as your initial statement use:
FROM [tbl_Item_Log] WHERE (1=1)
Since you have code to return the generated string, why not put that into SSMS and try to run it?
I also just noticed that if you don't pass in date values that you will end up executing a NULL string, because your final concatenation will end up causing a NULL. These are the kinds of things that you need to pay very close attention to if you're going to be using dynamic SQL to build queries.
Once I corrected that I was able to run the stored procedure without any errors (at least to generate what looks like a valid SQL statement). That leads me to believe that it may be a problem with data types in the underlying table. Can you provide the definition for that?
One last note: Personally, I would use
CONVERT(VARCHAR(11), RecDate, 106) AS RecDate
instead of the seemingly unnecessary subquery that you have.
Yet another edit:
You may want to remove the code that checks LTRIM(#Search_User_ID) <> ''. It's a pointless bit of code and perhaps a setting particular to your server/connection is causing it to fail because of the type mismatch.
IF (Search_User_ID IS NOT NULL)
needs an # symbol infront of the variable
You say you are passing empty string in for all variables but one is an int, it can't take an empty string that is not int data. Can't believe I didn;t notice that the first time.
Why don't you use single parameterized query like this:
select
recdid,
Vendor_Num,
Vendor_Name,
InvoiceNum,
Item_Num,
CONVERT(VARCHAR(11), RecDate, 106) as RecDate,
NeedsUpdate,
RecAddUserID
FROM
[tbl_ItemLog] as t
where
(((Item_num like #Item_Num + '%' and #Search_Type = 0) OR
(Item_num like '%' + #Item_Num + '%' and #Search_Type = 1) OR
(Item_num like '%' + #Item_Num + '%' and #Search_Type = 2))
OR
#Item_Num IS NULL) AND
(Vendor_Num = #Vendor_Num OR #Vendor_Num IS NULL) AND
(RecAddUserId = #Search_User_Id OR #Search_User_Id IS NULL) AND
(RecDate BETWEEN #StartDate AND #EndDate)
You really have several different stored procedures here. Why not just write them separately? Everything that's controlled by switch statements could be easily in procedural code. Same for the LTRIM calls.
You could call them all from a single SP with switch statements; but I think it's generally better to not merge them in the first place. The SP queries will optimize more easily, and the code will be simpified. There's not much you gain by consolidating them.
Not sure of your business rules, but you could simplify this outside SQL with
switch(search_type) {
case 1:
do_query_type_1(args);
break;
case 2:
do_query_type_2(args);
break;
case 3:
do_query_type_3(args);
break;
default:
whatever ...
}
Also it looks like you have separate logic for cases where the item number is provided or not. Same for other fields. Each of your use cases looks like it resolves to a pretty simple query.